josdejong / josdejong/pocomath
Some comments
- Dominant language
- JavaScript
- Stars
- 3
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
So far I just looked at the things you've done in the complex subdirectory, because I pretty much believe that without any generic types like `Complex` or `Vector` there would be no major hitch in doing things along these lines. I can't yet say that it will or won't work even so, but here are the concerns I see with the ones you have done so far:
1. In isReal.ts you have defined the generic function type IsReal, using up that generic. But undoubtedly we would want to have an isReal implementation for `number` that would always return true. How would that be typed, since you can't "extend" a generic? It's also slightly misleading/inconsistent in that elsewhere in the code, if I want to get the function type of `add` on arguments of type Foo I do `Add` but if I do `IsReal` I don't get the function type of `isReal` on an argument of type Foo, I get the function type of `isReal` on an argument of type `Complex`. How do I remember that? I am worried about not having a uniform way to obtain the function type of the operation with a given name on a given tuple of parameter types...
2. I really don't like that to specify the dependencies on add and equal, you have to mention the name of each one _three_ times: once in the argument, again in the type of the argument, and again in the template that gives the specific type of the dependency. I worked really hard to avoid such redundancy in typocomath. The first scheme had none, but when I couldn't get it to work, I accepted for now a doubling of the mention of the name of an operator, but only where it is defined: once in the name of the function and once in the template that checks its type. There is still only one mention of the operator name in each _use_ as a dependency, so that's not as bad as it could be because there are many more uses than definitions. And I'd still like to get rid of the doubling of the name at definition time, but haven't quite figured out how to do that yet (there are more pressing problems like just getting the whole thing to compile).
3. Then in arg.ts yet a third way to obtain the function type of an implementation is introduced: ArgComplexNumber (as opposed to `Arg>` or `Arg`, which I might guess it would be one of from the first two examples of `Add` and `isReal`. And if later other implementations of `arg` are added for other parameter types, it seems like we've started down the road of combinatorial explosion of type names; we might end up with an ArgComplexBigint and an ArgFoo and an ArgQuaternionNumber etc. etc.
4. Also I thought we wanted to do away with the extra layer of function call if there are no dependencies? In other words, the definition of arg there should just be `infer: z: Complex => Math.atan2(z.im, z.re)`, shouldn't it? Certainly in typocomath I have been leaving the dependencies off altogether when there are none, and I do think we can get Dispatcher (typed-function) to handle that.
5. In complex.ts, not sure what I would do with the `ComplexFn` generic -- there's not much TypeScript can do with unions of function types, sadly. And this introduces a fourth mechanism for finding the function type of an implementation: never mind the Fn suffix for now, since surely we can work out a naming convention that avoids that, but I now have to know/remember that to get the unary function type I use a 1 suffix and the binary I use a 2... I have a real worry that along these lines it will become a constant pain to look up/remember how to get the function type for each different dependency of a new operation I am writing. I am strongly in favor of a single minimally redundant notation for dependencies, based on my experience with writing current mathjs operations.
6. Incidentally (this is a minor point), as far as I can tell there is no way to actually make `zero()` a nullary function. Remember at runtime it is going to have to actually return the correct zero value, at least among number 0 and bigint 0n, which are different entities, and all type information is gone at runtime, so it has to have something it can use to tell what zero to return, so it needs to take an argument of the type of thing that the zero is wanted for...
7. In quaternion.ts, since you used the `ComplexFn` function type that is completely ambiguous between the unary and binary `complex()`, there could be no way for the Dispatcher (typed-function) to tell whether to supply the dependency as the unary or binary version of complex. So this would really need to be `ComplexFn2` for there to be any hope for the typed-function to get built properly.
OK, hopefully that makes some of the issues I have been grappling with clearer. I will add another batch of things to typocomath and then you can have a go at getting all of that working.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reading the implementations in the complex subdirectory, especially isReal.ts, arg.ts, complex.ts, and quaternion.ts, then compare their dependency typing with typocomath and Dispatcher (typed-function). The thread identifies several competing conventions but does not define a settled design or a concrete completion test; clarify the intended approach before changing code.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- tooling
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100