What is the motivation for Julia not dispatching on keyword arguments?

Compare to the existing optional positional arguments and you’ll see that specialization isn’t involved yet, it’s entirely about multimethods with respect to arity:

(This isn't code, I just need formatting) 
foo(a=1,b=2) = ...
generates
foo() = foo(1, 2)
foo(a) = foo(a, 2)
foo(a,b) = ...

n optional arguments make 1+n methods instead of just the original foo(a=1,b=2) because they need to overwrite previous (or be overwritten by subsequent) foo() and foo(a) methods to prevent ambiguous dispatch of calls.
Contrast that with hypothetical optional keyword arguments:

foo(;a=1,b=2) = ...
generates
foo() = foo(;a=1,b=2)
foo(;a) = foo(;a=a, b=2)
foo(;b) = foo(;a=1, b=b)
foo(;a, b) = ...

This short example doesn’t really show off the sum of combinations for space, but n optional keyword arguments would make \sum_{k=0}^{n} C(n, k)=2^n methods (2^n grows slower than the (1+n)! in the linked comment, see binomial theorem to prove that equality). That gets real big real fast, and the only way to avoid making so many methods (to store and to compile for) is to not make multiple methods with respect to keyword arguments.

That’s just one of the implementation problems, but even if there weren’t any, I wouldn’t even want to dispatch over keyword arguments. Despite the earlier optional positional arguments example, it’s far more typical that a foo(a) method does not forward to foo(a,b), but does something entirely different, e.g. -x vs x-y. On the other hand, keyword arguments basically exist to override a few select values in a large set of defaults, and that’s the only way writing arguments out of order has any convenience e.g. plot(x, y; color="red") does the same thing as plot(x, y; linestyle="dots"). Performance would still need specialization, and that does happen; reflection is harder but the underlying kwcall sorts the arguments into positional arguments and specializes over them.

6 Likes