I don’t really understand why in the following code Payload(;a, b) = Payload(a=a, b=b, c=Float64[]) fails. It looks a legitimate expression to me.
module Test
Base.@kwdef mutable struct Payload
a::Int
b::String
c::Vector{Float64}
end
Payload(;a, b) = Payload(a=a, b=b, c=Float64[])
@show Payload(a=1, b="apple")
end
WARNING: replacing module Test.
ERROR: MethodError: no method matching Main.Test.Payload(; a=1, b="apple", c=Float64[])
Closest candidates are:
Main.Test.Payload(; a, b) at E:\work\julia\test2.jl:8 got unsupported keyword argument "c"
Main.Test.Payload(::Int64, ::String, ::Vector{Float64}) at E:\work\julia\test2.jl:3 got unsupported keyword arguments "a", "b", "c"
Main.Test.Payload(::Any, ::Any, ::Any) at E:\work\julia\test2.jl:3 got unsupported keyword arguments "a", "b", "c"
Stacktrace:
[1] kwerr(kw::NamedTuple{(:a, :b, :c), Tuple{Int64, String, Vector{Float64}}}, args::Type)
@ Base .\error.jl:165
[2] Main.Test.Payload(; a::Int64, b::String)
@ Main.Test E:\work\julia\test2.jl:8
[3] top-level scope
@ show.jl:1045
[4] eval
@ .\boot.jl:368 [inlined]
This works fine:
module Test
Base.@kwdef mutable struct Payload
a::Int
b::String
c::Vector{Float64}
end
Payload(;a, b) = Payload(a, b, Float64[])
@show Payload(a=1, b="apple")
end
Ah, it looks like that default keyword outer constructor method is not provided once the user defines one for himself.
module Test
Base.@kwdef mutable struct Payload
a::Int
b::String
c::Vector{Float64}
end
@show methods(Payload)
Payload(;a, b) = Payload(a, b, Float64[])
@show methods(Payload)
@show Payload(a=1, b="apple")
end
WARNING: replacing module Test.
methods(Payload) = # 3 methods for type constructor:
[1] Main.Test.Payload(; a, b, c) in Main.Test at util.jl:489
[2] Main.Test.Payload(a::Int64, b::String, c::Vector{Float64}) in Main.Test at E:\work\julia\test2.jl:3
[3] Main.Test.Payload(a, b, c) in Main.Test at E:\work\julia\test2.jl:3
methods(Payload) = # 3 methods for type constructor:
[1] Main.Test.Payload(; a, b) in Main.Test at E:\work\julia\test2.jl:10
[2] Main.Test.Payload(a::Int64, b::String, c::Vector{Float64}) in Main.Test at E:\work\julia\test2.jl:3
[3] Main.Test.Payload(a, b, c) in Main.Test at E:\work\julia\test2.jl:3
Payload(a = 1, b = "apple") = Main.Test.Payload(1, "apple", Float64[])
Is this something similar in spirit to:
If any inner constructor method is defined, no default constructor method is provided: it is presumed that you
have supplied yourself with all the inner constructors you need.
No, it’s not that. But we don’t dispatch on kwargs, so when you define the (;a, b) constructor you overwrite the automatic (; a, b, c) constructor. They are both equivalent to a constructor with no arguments to dispatch.