ERROR: MethodError: no method matching Base.ImmutableDict(::Pair{Symbol,Int64}, ::Pair{Symbol,Int64})
Closest candidates are:
Base.ImmutableDict(::Pair{K,V}) where {K, V} at dict.jl:624
Base.ImmutableDict(::Base.ImmutableDict{K,V}, ::Pair) where {K, V} at dict.jl:625

how do you construct a multi-key immutable dictionary?

# this actually defines reverse iteration (e.g. it should not be used for merge/copy/filter type operations)
start(t::ImmutableDict) = t
next(::ImmutableDict{K,V}, t) where {K,V} = (Pair{K,V}(t.key, t.value), t.parent)
done(::ImmutableDict, t) = !isdefined(t, :parent)

is not very encouraging for merge!(d1::ImmutableDict,d2::ImmutableDict)

Yes, you are right. If you do merge!(d1,d2), then d1 will still be bound to the same unchanged object. So the name merge! is incorrect.

The method in the post you link is a solution for the (minimal) example given in the original questionâ€” but only for exactly two entries. In any case, I think that either the post you linked or my answer give enough information for @djsegal to construct something useful.

Strictly speaking there is no such thing like an ImmutableDict with multiple keys, theyâ€™re nested dictionaries. What you ask for is a convenience to build such object. Perhaps there arenâ€™t many people using this type? (I do.)

Isnâ€™t an ImmutableDict the immutable counterpart of a Dict?

Yes. From the documentation:

ImmutableDict is a Dictionary implemented as an immutable linked list.

The implementation is a particular singly-linked list. Each node has three fields, a key, a value, and a link to the parent node. The interface is that of a Dict, with some restrictions, partly due to the implementation as a linked list.

An immutable dict can certainly hold an arbitrary number of keys/values. Each node, of type ImmutableDict holds only one key/value pair. But, there is no container of these nodes that makes Dict; they are just linked together.

The interface does not allow construction with more than one key/value pair. But, a method to do this would be straightforward. My guess is that it was not needed for the task that this particular implementation was written for.

It sounds more appropriate to call this an ImmutablePair then?

Yes, I see what you mean. But this kinda ruins the illusion that you have a Dict.

And the parent list might be thought of as the ImmutableDict?

There is no parent list. Each node, including the parent node, is an instance of ImmuatableDict.

Iâ€™m not sure what your use case is. But, it is possible to construct an ImmuatbleDict from a list of pairs, and then to retrieve them. Itâ€™s just that the method is not written.

function Base.ImmutableDict(KV::Pair{K,V}, KVs::Pair{K,V}...) where {K,V}
d = Base.ImmutableDict(KV)
for p in KVs
d = Base.ImmutableDict(d,p)
end
return d
end