So this is an issue that I find after figuring out how the keyword arguments are currently implemented in Julia. It will probably not be an issue anymore if #2773 is implemented.
The document on methods says
Methods are dispatched based only on positional arguments, with keyword arguments processed after the matching method is identified.
However, method dispatch actually behaves differently when doing a function call with or without keyword arguments. i.e.
julia> function f(::Integer)
2
end
f (generic function with 1 method)
julia> function f(::Number; kw...)
1
end
f (generic function with 2 methods)
julia> f(1)
2
julia> f(1; a = 2)
1
What happens here is that f.env.kwsorter
only has one method defined and therefore when calling with keyword argument, f(::Integer)
does not participate in method dispatch.
IMHO, there are several possible ways to fix it,
env.kwsorter
even for methods that does not take keyword arguments. This can also avoid the following confusing abuse of overriding method``` julia
julia> function f(::Number; kw...)
1
end
f (generic function with 1 method)
julia> function f(::Number)
2
end
f (generic function with 1 method)
julia> f(1)
2
julia> f(1; a = 2)
1
```
This is probably the easiest way to fix the code and is consistent with the best long term behavior.
1.0
milestone, hopefully this will be eventually be implemented.see also https://github.com/JuliaLang/julia/issues/4469#issuecomment-39628582
I think we should add keyword arguments to the calling convention, replacing the existing kwsorter
-based implementation.
Currently, defining a keyword method actually defines three methods:
kwsorter
function that does sorting and calls method (1).My proposal merges methods (2) and (3):
Expr(:kwargs)
to access a keyword argument container passed as a pointer via the calling convention, and then does sorting.jl_call_method_internal
and its codegen throw an error if no kwarg-accepting entry point is available for a given kwarg call.Expr(:kwcall, ...)
that has a slot for a keyword arg container.Expr(:kwargs)
and will then be able to specialize the sorting code.It would be possible to get the performance aspect of this just by passing a different kind of container to our existing kwsorter, and changing its lowering to make it easier to specialize. However our current implementation is also very complex, and we'd still need a separate fix for the semantic issue described here. Having 2 methods instead of 3 will also make reflection easier. So I think this redesign should be considered.
This shouldn't have been closed, yet, I guess. Or did I miss something?
Will have to punt on this for 1.0.
I think we should add keyword arguments to the calling convention, replacing the existing kwsorter-based implementation
Any chance that this will make it into a 1.x release?
No, it would be a breaking change.
Just for a reference. The current behavior has the following consequence:
julia> f(x::Int; y=1) = 2
f (generic function with 1 method)
julia> f(x::Int) = 1
f (generic function with 1 method)
julia> f(100)
1
julia> f(100, y=1)
2
but
julia> g(x::Int) = 1
g (generic function with 1 method)
julia> g(x::Int; y=1) = 2
g (generic function with 1 method)
julia> g(100)
2
julia> g(100, y=1)
2
Most helpful comment
Will have to punt on this for 1.0.