Add return convention choice to config and implement sqrt for all relevant types. #25
Loading…
Add table
Add a link
Reference in a new issue
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?
As per the discussion in https://github.com/josdejong/mathjs/issues/3374, we want to have a "free" return mode in which nanomath can use the "best" type for the return value of an operation, which could be "simpler" than the input types (like a bigint resulting from some fraction operation) or more "complicated" than the input types (like a Complex coming from an operation on numbers). But we also need a return mode in which there is one single type that can result from a given operation on particular types. In fact, there's a presumption that there's a need for mathjs existing
predictable = true
mode, in which the output type matches the input types insofar as possible, perhaps using NaN in the case of number, and throws if that simply is not possible. But for the sake of chaining in the internal implementations of nanomath methods, there also appears to be a need for a "fully defined" mode, in which the single return type is chosen so that the operation will always have an appropriately mathematically accurate result regardless of the specific values of the arguments, so long as the arguments are of the particular types.Add predictable to config and implement sqrt for all relevant types.to Add return convention choice to config and implement sqrt for all relevant types.Therefore, we are going to prototype the following system as an experiment. It differs from current mathjs, so if the prototype is deemed successful, we will have to contemplate how to "match up" the system as we adapt mathjs onto the nanomath engine. But it seems as though this is an opportunity to explore options, and that the system may offer worthwhile benefits, so it's worth a try.
We will set up a
returnTyping
enumeration, for now with three values:free
,conservative
, andfull
, corresponding to the three strategies described above for choosing return types from operations. The stored (factory-produced, final) behaviors for a given operation will be indexed not only by the argument types, but also by thereturnTyping
value. Therefore,resolve
will have a second argument, areturnTyping
value. It will default to thereturnTyping
property in the current configuration, but can also simply be specified directly, so that implementations can choose their desired return typing strategy for their dependencies without disrupting the configuration. Moreover, behaviors will not need to change when the configuration changes; simply different behaviors can be selected (and generated as needed).Finally, there is an issue as to what the value of the
.returns
property will be on behaviors that were generated under thefree
strategy and so might return one of two or more different types. It appears there is no choice but to add something nanomath has resisted so far: true union types that represent the set-theoretic union of two or more types. That feature could create some complexity in resolution. Currentlymath.resolve()
is used in two ways: (A) to choose which behavior to call on a specific list of arguments, and (B) for implementations to choose which behavior of their dependencies to compile into their own behavior when building it in a factory. In use (A), there can only be single concrete types for each argument, as each one is assigned a specific type bymath.typeOf
. However, in (B), imagine that an implementation wants to applymultiply
to the result ofsqrt
under thefree
strategy. That result may well be a union. Since nanomath behaviors are meant to deal with specific types, there wouldn't really be a way to resolve thatmultiply
with a single function. In other words, it seems like it will be necessary to maintain the convention that the type-list argument toresolve
remains single types. In that case, implementations that want to deal with dependencies with thefree
strategy may need facilities to unpack the unions, and resolve multiple behaviors for their other dependencies, and select among them at runtime depending on the type that actually results from thefree
-strategy dependency. Of course, this may simply mean that implementations in practice never use thefree
return typing strategy for their dependencies. That's part of the point of this prototype.