KeywordCalls.jl
KeywordCalls.jl copied to clipboard
Default values bug with multiple `@kwcall`
Oh no, I think there's a bug hidden inside the default values-
julia> using KeywordCalls
julia> foo(nt::NamedTuple{(:a, :b)}) = nt.a + nt.b
julia> foo(nt::NamedTuple{(:c, :d)}) = nt.c * nt.d
julia> @kwcall foo(a, b=0)
julia> foo(a=2)
2
julia> foo(a=4, b=10)
14
second @kwcall
julia> @kwcall foo(c, d=0)
julia> foo(c=2)
0
julia> foo(c=4, d=1)
4
but now the foo(a,b) defaults are lost-
julia> foo(a=2)
ERROR: MethodError: no method matching _call_in_default_order(::typeof(foo), ::NamedTuple{(:a, :d), Tuple{Int64, Int64}})
Closest candidates are:
_call_in_default_order(::typeof(foo), ::NamedTuple{(:a, :b), T} where T<:Tuple) at C:\Users\miles\.julia\packages\KeywordCalls\d3x9F\src\KeywordCalls.jl:40
_call_in_default_order(::typeof(foo), ::NamedTuple{(:c, :d), T} where T<:Tuple) at C:\Users\miles\.julia\packages\KeywordCalls\d3x9F\src\KeywordCalls.jl:40
Stacktrace:
[1] foo(nt::NamedTuple{(:d, :a), Tuple{Int64, Int64}})
@ Main C:\Users\miles\.julia\packages\KeywordCalls\d3x9F\src\KeywordCalls.jl:41
[2] foo(; kw::Base.Iterators.Pairs{Symbol, Int64, Tuple{Symbol}, NamedTuple{(:a,), Tuple{Int64}}})
@ Main C:\Users\miles\.julia\packages\KeywordCalls\d3x9F\src\KeywordCalls.jl:42
[3] top-level scope
@ REPL[27]:1
I see, it's the middle line here:
q = quote
KeywordCalls._call_in_default_order(::typeof($f), nt::NamedTuple{($(sorted_args...),)}) = $f(NamedTuple{($(args...),)}(nt))
$f(nt::NamedTuple) = KeywordCalls._call_in_default_order($f, _sort(merge($defaults, $alias($f, nt))))
$f(; kw...) = $f(merge($defaults, $alias($f, NamedTuple(kw))))
end
There can only be one f(nt::NamedTuple) method, so it's rewritten each time