Mergewith(dicts...)

Why does this discard the first dict instead of merging? This signature is undocumented.

julia> mergewith(Dict(1=>10), Dict(2=>20))
Dict{Int64, Int64} with 1 entry:
  2 => 20

If the signature is undocumented this is undefined behaviour and you should not rely on it.

eh, you just want


julia> merge(Dict(1=>10), Dict(2=>20))
Dict{Int64, Int64} with 2 entries:
  2 => 20
  1 => 10

merge with takes an “combine” function

1 Like

It should give an error in this case, no?

maybe, but we probably have 1000:
“this works because our functions are general enough but users probably don’t want this behavior”

this particular case is just because

function mergewith!(combine, d::AbstractDict, others::AbstractDict...)
    foldl(mergewith!(combine), others; init = d)
end

we just returned init=d I guess

and the fact that this is un-typed

mergewith!(combine) = (args...) -> mergewith!(combine, args...)

maybe type this with:

julia> Base.Callable
Union{Function, Type}

?

Yes, that seems like it should be typed with a Callable check, to avoid this type of issue. This “working” without error is an unfortunate consequence of the fact that the combine “operator” Dict(1 => 10) is never actually used, since according to mergewith! (and its called functions) there’s only an initial value here, Dict(2=>20), so nothing to reduce using the operator. So passing anything at all as the first argument will work, as long as there’s only one other argument to the function.

julia> mergewith(Main, Dict(2=>20))
Dict{Int64, Int64} with 1 entry:
  2 => 20

julia> mergewith(π, Dict(2=>20))
Dict{Int64, Int64} with 1 entry:
  2 => 20

julia> mergewith("this is free real estate", Dict(2=>20))
Dict{Int64, Int64} with 1 entry:
  2 => 20

I’m not sure if the non-specialization penalty of Function applies to Callable too. If it does, an explicit check of combine isa Callable seems worth doing to avoid this quite unintuitive behaviour.

Jeff says

Callable should not be used anymore.

exactly, so nothing can be done here, even if you error on combine::AbstractDict, there are so many other types that is “probably wrong”