Implement basic dispatch. #10
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
I believe all is ready to write a simple dispatcher.
Yes! Are you going to give this a shot? As soon as there is a bare-bone implementation, I think I can start working on implementing more functions for it.
Indeed, I have already begun playing around with the code. Since this is a prototype/proof of concept, I was going to take an initial stab at a slightly different architecture for the dispatcher:
In typed-function, signatures are sorted, and then selected by type-testing the actual arguments one-by-one against each signature. The operation "typeOf" is then implemented by assembling a number of constant functions with different signatures.
In the initial prototype I am trying, the operation "typeOf" will be more fundamental, and implemented by special-purpose code that goes through the sorted list of registered types. Then to dispatch a call, typeOf is applied to the actual arguments to produce a string encoding the actual argument call signature, e.g.
number,Complex<number>,string
. This string is then used as a key with which to look up the proper implementation. If the lookup fails, there will be a backup implementation that for example checks if any new template instantiations need to be created to handle this argument list (updating the lookup table for the operation, if so, before dispatching to that implementation).A couple of questions:
(A) Do you know of any reason why actual-call-signature based hash map lookup to get the implementation, rather than sequential run-the-type-tests selection, is a bad idea?
(B) If not, do you have any intuition as to whether it's better to use a JavaScript Map or a plain object for the hash map from signature keys to implementations?
OK, I have pushed https://code.studioinfinity.org/glen/math5/src/branch/feat/dispatch_type. If you run it (with
pnpm go
), you should see that it is correctly typing numbers and (possibly nested, i.e. quaternion) Complex numbers. That's all it does so far; it ignores all implementations. Next step is to record all of the implementations and then build the actual behaviors, or at least a first pass at them. In addition to the questions in the previous comment:(C) Any comments/thoughts so far?
(D) Rather than just build up a long index.ts that tries various things, I thought it would be good right away to switch to a test harness and implement
pnpm test
and put all of the expected outputs, like the type tests for these sample values, into the tests. Do you have a recommended test harness for us to use? I checked to refresh my memory and mathjs uses mocha; is that your preference, or is there something you feel would be better in this prototype situation? I see I also used mocha in thepocomath
prototype, which was the last one to have a test harness, if I recall. So I am assuming that's the way to go, but thought I'd get your input before setting one up here, in case your preferences have changed.P.S. Note that pocomath was strictly limited to a single type parameter for any generic type. You will see a couple of code changes in this branch attempting not to lock math5 into this same restriction. I don't specifically have a use case for a generic type with more than one type parameter, but I do have the sense that we might regret the restriction if we bake it in. One example that is not too contrived is that mathjs has a "function" type; math5 might conceivably want to have a
Function<Domain, Range>
type. Of course, to make that work for multi-argument functions, we would need to be able to deal with TypeScript tuple types, so that we could writeFunction<[number,number,string], boolean>
for a function that takes 3 arguments, two numbers and a string, and returns a boolean. Anyhow, that's all very speculative; at the moment just mentioning that I am also trying to allow for multiple type parameters in this prototype.(A) About the actual-call-signature idea: I think a drawback may be performance, but it really requires a benchmark to figure that out (creating strings is slow, but a lookup in a map is fast). It could also be that it actually is faster.
(B) I think it would be a good idea to use
Map
, since using object comes with some security risks (object contains proto, constructor, toString, etc and you have to usehasOwnProperty
and stuff like that). Also, Map seems to be as fast or faster as object.(C) No other thoughts so far (though really happy to see the first actual code doing stuff :) )
(D) Yes I love setting up tests in an early stage. I have a preference for using
vitest
. Vitest works out of the box with TypeScript, ESM, etc. For bundling we use the Library Mode ofvite
.Sounds good. Let's keep an eye on the complexity that it adds, if that grows unwieldy it may help to choose some limitation. I don't expect that though, and you're right, it's easy to add now but hard to add in a later stage.
OK, given that all looks good so far, and signature-based dispatch isn't necessarily a totally stupid idea, I am going to just go ahead and merge into main. Next step will be to add tests with vitest, I'll file an issue for this and then do a PR that we will make sure runs for you before it's merged. Thanks!