Concern with merging exports #29
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?
The Pocomath architecture is based on bundling up signatures. Currently each type's version of each operation is in a separate file (although they could be clumped more, say by type and then topic group like arithmetic, relational, logical, cobinatorics, etc) and they are then collected via reexporting into clumps, and then collected into larger clumps, and then finally installed into a PocomathInstance.ed
The potential difficulty arises when clumps are aggregated that define different signatures for the same operation. Currently, these are exported as different values for the same identifer (the operation). But when you do
the resulting module can only have one value for an identifer 'foo'. So if A and B each put different signatures on foo, (at least) one of the contributions is going to be lost.
(Aside: JavaScript doesn't seem to complain about the conflict. But it does have some kind of resolution mechanism, which seems to sometimes end up with the module in which two different versions of foo are re-exported with export * having no definition of foo.)
So far, I have gotten everything to work by explicitly exporting the version of any conflicting signature that I want in such collecting-up modules. But in the last PR it became a bit of a pain, and it does not feel scalable.
Ideally in our setting, what we'd like is for the two versions of foo to merge as objects, since they presumably define disjoint signatures for the ultimate operation. But that is definitely not in the realm of JavaScript semantics.
So here are some alternatives:
We chould change the notation, so that rather than exporting, for example, the identifier
sqrt
as an object with keyComplex
(for its signature 'Complex'), we would export the identifiersqrt_Complex
with the specification of the implementation for that signature. Then if the signatures are disjoint, all of the symbols do just accumulate without conflict, and they can all be installed. This is basically what happened with types: identifier Types with key Complex became identifier Type_Complex, for basically the identical reasons. However, this approach does not seem very comfortable for the operations themselves: aside from its basic inelegance, the suffixes here would be full-blown signatures, rather than just a type identifier (which can much more easily be limited to a JavaScript identifier). Everything in a signature would have to be shoehorned into a valid identifier, which will end up just plain ugly. Plus we know the import/export doesn't actually complain about collisions, so we won't have an error check on unintentional signature clashes.We could add a utility to merge imports, something like
Then we can put all the clever merging and conflict checking we want into FuseExports. (In fact, we could switch back to putting types onto a single Types property, if that seems nicer.)
An advantage here is that we can just use separate methods for types and operations, getting rid of special identifiers like
Type_Complex
altogether.So a module that provides the type Complex might look like:
And a module that uses this might look like:
This seems pretty clean, but does have a bit of boilerplate to it...
with PocomathInstance:
All that needs to be done here is to allow the
merge
static function of PocomathInstance to take any number of arguments, each of which can either be a plain object with operator/type identifiers, or another PocomathInstance, and have it merge them all together sanely. Then we won't rely on Javascript's default re-export merging, but there shouldn't be much code overhead.Option 4 seems to be the way to go.
Option 5:
Like option 4, but have the merging just be a little more clever so that you can always say
without having to worry about how A and B exported. The advantage here is that we can get rid of the magic names for type exports and instead export a type exactly as in option 3 above, but use it with less boilerplate like so:
and everything should just work.
I will give option 5 a try.