I'm trying to splat a Dict{Symbol, Any}
into a struct that I created with @kwdef
, it looks like I've defined the method: MyStruct(; abc)
, but it's not interpreting the splat as keyword arguments, instead as positional arguments.
julia> Base.@kwdef struct MyStruct
abc::Int64
end
julia> methods(MyStruct)
# 3 methods for type constructor:
[1] MyStruct(; abc) in Main at util.jl:493
[2] MyStruct(abc::Int64) in Main at Untitled-2:5
[3] MyStruct(abc) in Main at Untitled-2:5
julia> x = Dict(:abc=>123)
julia> MyStruct(x...)
ERROR: MethodError: Cannot `convert` an object of type Pair{Symbol, Int64} to an object of type Int64
Closest candidates are:
convert(::Type{T}, ::T) where T<:Number at number.jl:6
convert(::Type{T}, ::Number) where T<:Number at number.jl:7
convert(::Type{T}, ::Base.TwicePrecision) where T<:Number at twiceprecision.jl:273
...
Stacktrace:
[1] MyStruct(abc::Pair{Symbol, Int64})
@ Main ./Untitled-2:5
[2] top-level scope
@ Untitled-2:11
You need to do MyStruct(; x...)
so that julia knows you're splatting as keyword aguments, not regular arguments
julia> MyStruct(; x...)
MyStruct(123)
Maybe this helps clear it up:
julia> f(x...) = println("got arguments: ", x);
julia> f(;x...) = println("got keyword arguments: ", x);
julia> f(x...)
got arguments: (:abc => 123,)
julia> f(;x...)
got keyword arguments: Base.Pairs(:abc => 123)
Ah, of course, so obvious in hindsight! Thanks!
Hannes has marked this topic as resolved.
Happy to help :smile:
My rule of thumb is: _always_ start keyword arguments with semicolon and you don't need to remember about these corner cases
imho kwargs should require ;
Last updated: Nov 06 2024 at 04:40 UTC