API to specify a function name and multiple signatures in a single file #12

Open
opened 2025-04-09 16:01:03 +00:00 by josdejong · 1 comment
Collaborator

I've been reading https://code.studioinfinity.org/StudioInfinity/nanomath/wiki/Item-Specifications, and now I'm thinking about how to specify multiple signatures of a single function in a single file in a neat way.

Maybe it is interesting to do something like this, putting the function name as a factory function argument:

const add = onType('add', [Complex, Complex], (math, [T, U]) => { ... })

And then, to implement multiple signatures:

const add = [
  onType('add', [number, number], (math) => { ... }),
  onType('add', [Complex, Complex], (math, [T, U]) => { ... }),
  // ...
]

Or maybe rename onType into create or factory, for example:

const add = [
  create('add', [number, number], (math) => { ... }),
  create('add', [Complex, Complex], (math, [T, U]) => { ... }),
  // ...
]

Thinking about it, it could also just be wrapping signatures in an array:

const add = [
  onType([number, number], (math) => { ... }),
  onType([Complex, Complex], (math, [T, U]) => { ... }),
  // ...
]

What do you think?

I've been reading https://code.studioinfinity.org/StudioInfinity/nanomath/wiki/Item-Specifications, and now I'm thinking about how to specify multiple signatures of a single function in a single file in a neat way. Maybe it is interesting to do something like this, putting the function name as a factory function argument: ```js const add = onType('add', [Complex, Complex], (math, [T, U]) => { ... }) ``` And then, to implement multiple signatures: ```js const add = [ onType('add', [number, number], (math) => { ... }), onType('add', [Complex, Complex], (math, [T, U]) => { ... }), // ... ] ``` Or maybe rename `onType` into `create` or `factory`, for example: ```js const add = [ create('add', [number, number], (math) => { ... }), create('add', [Complex, Complex], (math, [T, U]) => { ... }), // ... ] ``` Thinking about it, it could also just be wrapping signatures in an array: ```js const add = [ onType([number, number], (math) => { ... }), onType([Complex, Complex], (math, [T, U]) => { ... }), // ... ] ``` What do you think?
Owner

Well currently I just allow

const add = onType(
   [Number, Number], (math) => { ... },
   [Complex, Complex], (math, [T, U]) => { ... }
)

(see src/core/__test__/TestDispatcher.spec.js at line 20, for example). In other words, you can just alternate type patterns and corresponding values, for as many or few as you like (often just one pair). This convention seemed to me to be the simplest analogue of the object key - value interface in mathjs 14. But do you like it better how it looks if you repeat onType for each type pattern?

Or if you like a list of pairs better, we could switch to

const add = onType(
   [[Number, Number], (math) => { ... }],
   [[Complex, Complex], (math, [T, U]) => { ... }],
)

or something like that.

Another alternative, if you don't mind repeating a function symbol, would be:

export const add = {
   [pattern(Number, Number)]:  (math) => { ... },
   [pattern(Complex, Complex)]: (math, [T, U]) => { ... },
}

Here we avoid parsing by having our pattern function set up to return a string which more or less acts like a hash -- it puts the actual TypePattern object into some global repository, keyed by that string. Then when this add definition gets merged into the TypeDispatcher, it looks up the keys of the object associated with add in that global repository to find the TypePatterns it should use. Don't get me wrong, the string returned by pattern could be human-readable; it just has to be different for each different TypePattern.

But the notation I currently implemented is the most concise one I could think of.

Let me know which of these conventions you prefer and if it's different than the current one, I will make a PR to switch this prototype over. Same goes if you come up with some "sleeker" for return-type annotations.

Well currently I just allow ``` const add = onType( [Number, Number], (math) => { ... }, [Complex, Complex], (math, [T, U]) => { ... } ) ``` (see `src/core/__test__/TestDispatcher.spec.js` at line 20, for example). In other words, you can just alternate type patterns and corresponding values, for as many or few as you like (often just one pair). This convention seemed to me to be the simplest analogue of the object key - value interface in mathjs 14. But do you like it better how it looks if you repeat `onType` for each type pattern? Or if you like a list of pairs better, we could switch to ``` const add = onType( [[Number, Number], (math) => { ... }], [[Complex, Complex], (math, [T, U]) => { ... }], ) ``` or something like that. Another alternative, if you don't mind repeating a function symbol, would be: ``` export const add = { [pattern(Number, Number)]: (math) => { ... }, [pattern(Complex, Complex)]: (math, [T, U]) => { ... }, } ``` Here we avoid parsing by having our `pattern` function set up to return a string which more or less acts like a hash -- it puts the actual TypePattern object into some global repository, keyed by that string. Then when this `add` definition gets merged into the TypeDispatcher, it looks up the keys of the object associated with `add` in that global repository to find the TypePatterns it should use. Don't get me wrong, the string returned by `pattern` could be human-readable; it just has to be different for each different TypePattern. But the notation I currently implemented is the most concise one I could think of. Let me know which of these conventions you prefer and if it's different than the current one, I will make a PR to switch this prototype over. Same goes if you come up with some "sleeker" for return-type annotations.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: StudioInfinity/nanomath#12
No description provided.