let
a = (a=1, b=2)
b = Dict(:c=>3, :d=>4)
merge(a, b)
end
(a = 1, b = 2, d = 4, c = 3)
but merge(b, a)
fails with MethodError
. Is the method simply not implemented, or am I missing why it's a bad idea?
Dict keys don't have to be symbols, idk if that's the reason tho
I think that's what I was missing. NamedTuple keys must be symbols.
maybe this could be defined for Dict{Symbol,T}
? would that be a good idea?
As an alternative, I found that one can do
let
a = (a=1, b=2)
b = Dict(:c=>3, :d=>4)
merge(NamedTuple(b), a)
end
(d = 4, c = 3, a = 1, b = 2)
mbaz said:
I think that's what I was missing. NamedTuple keys must be symbols.
I don't clearly see how this leads to merge(::Dict, ::NamedTuple)
not being defined while the other way around is defined.
merge
docs don't mention any asymmetry regarding key types - there's only "If necessary, the types of the resulting collection will be promoted to accommodate the types of the merged collections".
And if there is asymmetry, my mental model would be that the first argument's key type would be the "primary" one that the rest of them should adhere to - so if anything, Dict
being the second argument should be the problematic case (if we're assuming asymmetry at all).
I think (unless I'm missing something) it's just a missing implementation - something like merge(itr, a::NamedTuple) = merge(a::NamedTuple, itr)
.
I think this operation doesn't make sense. getindex
and getproperty
are different projectors. There could be a type that has both, with different values for the same key.
I'm not so sure about the idea behind merge
or even pairs/keys/values
really.
@Sundar R How could Dict("1"=>"V")
be converted to a NamedTuple
? A NamedTuple
restricts the type of the keys, whereas a Dict
doesn't.
@Sundar R Maybe what merge
should do is not to promote the keys, but to promote the resulting container so that it can accomodate all k,v pairs being merged.
For example, the docs say
merge(a::NamedTuple, iterable)
Interpret an iterable of key-value pairs as a named tuple, and perform a merge.
which seems to imply any iterable can be merged into a NamedTuple, but that's not the case:
merge((a = true,), Dict("1" => 1.5))
ERROR: TypeError: in typeassert, expected Symbol, got a value of type String
This fails because it wants to return a NamedTuple
, but it should (?) return a Dict
.
@jar Why do you think merge
makes no sense? Sometimes you have two containers and want to combine them.
Hit this recently and thought it was weird that it didn't just return a dict too.
mbaz said:
Sundar R How could
Dict("1"=>"V")
be converted to aNamedTuple
? ANamedTuple
restricts the type of the keys, whereas aDict
doesn't.
Yeah, I understand that part, but if merge
is symmetric between its arguments (i.e. treats them the same), then it shouldn't matter which order we send a Dict
and NamedTuple
in: either both merge(::Dict, ::NamedTuple)
and merge(::NamedTuple, ::Dict)
work, or neither does. Passing a non-Symbol keyed Dict as second argument currently throws a TypeError
, and with merge(itr, a::NamedTuple) = merge(a::NamedTuple, itr)
it would do the exact same for the other way around too.
It's weird to treat these cases differently and give different errors, which is what leads me to think it's an implementation oversight and not a conscious design decision.
Yeah -- the order of the arguments might be relevant (as it is now) to decide what to do in case of repeated keys, but not to decide on the type of the result.
I wonder if it's worth it to open an issue about it.
Last updated: Nov 06 2024 at 04:40 UTC