Stream: helpdesk (published)

Topic: Merging Dict and NamedTuple


view this post on Zulip mbaz (Mar 21 2022 at 22:33):

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?

view this post on Zulip jar (Mar 21 2022 at 22:56):

Dict keys don't have to be symbols, idk if that's the reason tho

view this post on Zulip mbaz (Mar 21 2022 at 22:59):

I think that's what I was missing. NamedTuple keys must be symbols.

view this post on Zulip pg. (Mar 22 2022 at 00:45):

maybe this could be defined for Dict{Symbol,T} ? would that be a good idea?

view this post on Zulip mbaz (Mar 22 2022 at 01:55):

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)

view this post on Zulip Sundar R (Mar 31 2022 at 19:33):

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).

view this post on Zulip jar (Mar 31 2022 at 20:15):

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.

view this post on Zulip jar (Mar 31 2022 at 20:19):

I'm not so sure about the idea behind merge or even pairs/keys/values really.

view this post on Zulip mbaz (Mar 31 2022 at 21:35):

@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.

view this post on Zulip mbaz (Mar 31 2022 at 21:41):

@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.

view this post on Zulip mbaz (Mar 31 2022 at 21:43):

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

view this post on Zulip mbaz (Mar 31 2022 at 21:45):

This fails because it wants to return a NamedTuple, but it should (?) return a Dict.

view this post on Zulip mbaz (Mar 31 2022 at 21:48):

@jar Why do you think merge makes no sense? Sometimes you have two containers and want to combine them.

view this post on Zulip Zachary P Christensen (Mar 31 2022 at 21:55):

Hit this recently and thought it was weird that it didn't just return a dict too.

view this post on Zulip Sundar R (Mar 31 2022 at 22:00):

mbaz said:

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.

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.

view this post on Zulip mbaz (Mar 31 2022 at 22:05):

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 22 2024 at 04:41 UTC