# Way to construct multi-key ImmutableDict

**URL:** <https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294>\
**Category:** General Usage\
**Tags:** question\
**Created:** [April 12, 2018, 2:25am UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294 "2018-04-12T02:25:52Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![djsegal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djsegal/32/13752_2.png) [@djsegal](https://discourse.julialang.org/u/djsegal)\
**Post date:** [April 12, 2018, 2:25am UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/1 "2018-04-12T02:25:52Z")

</div>

if you try to do,

```julia
julia> Base.ImmutableDict(
         :a => 1,
         :b => 2
       )

```

you get,

```julia
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?

---

<div class="post-metadata">

**Author:** ![Ralph\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ralph_smith/32/10344_2.png) [@Ralph\_Smith](https://discourse.julialang.org/u/Ralph_Smith)\
**Post date:** [April 12, 2018, 2:59am UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/2 "2018-04-12T02:59:22Z")

</div>

with the (undocumented!) constructor

```julia
ImmutableDict{K,V}(parent::ImmutableDict, key, value) where {K,V} = new(parent, key, value)

```

or more typically via the convenience version:

```julia
    d = ImmutableDict(:a => 1)
    d1 = ImmutableDict(d, :b => 2)

```

(I learnt this from the test suite.)

---

<div class="post-metadata">

**Author:** ![djsegal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djsegal/32/13752_2.png) [@djsegal](https://discourse.julialang.org/u/djsegal)\
**Post date:** [April 12, 2018, 4:22am UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/3 "2018-04-12T04:22:14Z")

</div>

Is there a way to combine this with:

> [@Stack overflow when merging 50000 dicts](https://discourse.julialang.org/t/stack-overflow-when-merging-50000-dicts/10222/2):
>
> Okay, found a solution: merge!(Dict(), a...) is very fast…

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [April 12, 2018, 5:47am UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/4 "2018-04-12T05:47:53Z")

</div>

In `dict.jl`, this:

```julia
# 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)`

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [April 12, 2018, 6:07am UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/5 "2018-04-12T06:07:30Z")

</div>

Defining this method is useful for populating an `ImmutableDict` from single `Dict`.

```julia
function Base.merge!(d::Base.ImmutableDict, dsrc::Dict)
    for (k,v) in dsrc
        d = Base.ImmutableDict(d,k=>v)
    end
    return d
end

```

```julia
julia> dsrc = Dict(1=>2, 3=>4);

julia> d = merge!(Base.ImmutableDict{Int,Int}(), dsrc)
Base.ImmutableDict{Int64,Int64} with 2 entries:
  1 => 2
  3 => 4

```

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [April 12, 2018, 9:28am UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/6 "2018-04-12T09:28:23Z")

</div>

`ImmutableDict` is immutable, thus strictly speaking `merge!` doesn’t apply to it.

The answer to your original question was also here (found just by looking up “ImmutableDict” here, there are just 4 results): [Initialising a dictionary with duplicate keys - #3 by giordano](https://discourse.julialang.org/t/initialising-a-dictionary-with-duplicate-keys/2290/3)

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [April 12, 2018, 10:26am UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/7 "2018-04-12T10:26:09Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![djsegal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djsegal/32/13752_2.png) [@djsegal](https://discourse.julialang.org/u/djsegal)\
**Post date:** [April 17, 2018, 10:07pm UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/8 "2018-04-17T22:07:06Z")

</div>

> [@giordano](#):
>
> ImmutableDict is immutable, thus strictly speaking merge! doesn’t apply to it.

This is true, but a `Dict` usually has more than one or two entries?

> [@jlapeyre](#):
>
> but only for exactly two entries

Can someone explain why `ImmutableDict` doesn’t allow construction with multiple pairs to begin with?

I just thought the `merge!` trick would allow you to do this under the hood.

// not really trying to make `ImmutableDicts` mutable

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [April 17, 2018, 10:26pm UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/9 "2018-04-17T22:26:36Z")

</div>

> [@djsegal](#):
>
> but a `Dict` usually has more than one or two entries?

I’m not sure what are you referring to.

> [@djsegal](#):
>
> Can someone explain why `ImmutableDict` doesn’t allow construction with multiple pairs to begin with?

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

---

<div class="post-metadata">

**Author:** ![djsegal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djsegal/32/13752_2.png) [@djsegal](https://discourse.julialang.org/u/djsegal)\
**Post date:** [April 17, 2018, 10:31pm UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/10 "2018-04-17T22:31:03Z")

</div>

Isn’t an `ImmutableDict` the immutable counterpart of a `Dict`?

`Dicts` usually have multiple keys (or you would just make them into a variable)?

* * *

By example,

```julia
Base.ImmutableDict(
    :a => 1,
    :b => 42,
    :c => 404
 )

```

is how I would usually use a Dict. Not just:

```julia
Base.ImmutableDict(
    :a => 1
 )

```

In this case, I would just use a variable:

```julia
a = 1

```

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [April 17, 2018, 11:19pm UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/11 "2018-04-17T23:19:22Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![djsegal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djsegal/32/13752_2.png) [@djsegal](https://discourse.julialang.org/u/djsegal)\
**Post date:** [April 17, 2018, 11:27pm UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/12 "2018-04-17T23:27:56Z")

</div>

It sounds more appropriate to call this an `ImmutablePair` then?

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

But maybe my point/use-case doesn’t make any sense?

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [April 17, 2018, 11:37pm UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/13 "2018-04-17T23:37:18Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [April 17, 2018, 11:48pm UTC](https://discourse.julialang.org/t/way-to-construct-multi-key-immutabledict/10294/14 "2018-04-17T23:48:53Z")

</div>

```julia
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

```

```julia
julia> Base.ImmutableDict(
           :a => 1,
           :b => 42,
           :c => 404
        )

ImmutableDict{Symbol,Int64} with 3 entries:
  :c => 404
  :b => 42
  :a => 1
`

```

```julia

```
