Does Union-splitting the two possible concrete types for m
not remove dynamic dispatches? Or is Union-split code not trimmable for another reason?
In general cases though I agree with this approach to static code.
It’s only the two-language problem if we’re writing essentially the same code in another language. Putting aside the already addressed caveat that there aren’t 2 languages, I would argue that working with sum types, even if wholly internally like this, is semantically different enough from dynamically dispatching over runtime types. We wouldn’t call edits for multithreading or GPU arrays to be a two-language problem for the same reason. As nice as easy @static_please <expr>
and @multithread_please <expr>
macros would be, programming isn’t that declarative.
I think the juliac talks did speculate on more aggressive whole-program optimizations that branch over more types in an inferred Union
. But it wasn’t clear what the limitations there are; I believe I’ve read that Julia is too slow to build if the compiler generally tries to compile 10 possibilities instead of falling back to dynamic dispatch. Sum types on the other hand can be isolated to specified contexts instead, and they at their best would require about the same code as anything handled by a macro or compiler at their best (sum(variant(m))
is a lot shorter than a trivial match statement repeating an expression, though I’m not sure how variant
calls are type-stable).