# How can I get a fully-specified type of a \`Dict\`?

**URL:** https://discourse.julialang.org/t/how-can-i-get-a-fully-specified-type-of-a-dict/112570
**Category:** General Usage
**Created:** [April 5, 2024, 2:18pm UTC](https://discourse.julialang.org/t/how-can-i-get-a-fully-specified-type-of-a-dict/112570 "2024-04-05T14:18:30Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![scheidan1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scheidan1/32/24771_2.png) [@scheidan1](https://discourse.julialang.org/u/scheidan1)
#### Post date: [April 5, 2024, 2:18pm UTC](https://discourse.julialang.org/t/how-can-i-get-a-fully-specified-type-of-a-dict/112570/1 "2024-04-05T14:18:30Z")

</div>

Hi all,

I’m working in a package where the user provides a `Dict` that is never changed by my package. While I know the structure of the entries, I do not know the which types it contains. Is there a way to “convert” a poorly typed dict in a fully specified one for optimal performance?

A simplified example would look like this. A user provides `d1`:

```Julia
d1 = Dict{Any, Vector}()
d1[3] = [(1, "aaa"), (2, "aaa")]
d1[5] = [(1, "aaa"), (2.4, :bbb), (5.4, :bbb)]

```

`d1` is not fully specified. The fully-specified version of it is much faster but harder to write and less convenient for the user:

```Julia
d2 = Dict{Int,
          Vector{Union{Tuple{Int, String},
                       Tuple{Float64, Symbol}}}}() # a rather complicated type
d2[3] = [(1, "aaa"), (2, "aaa")]
d2[5] = [(1, "aaa"), (2.4, :bbb), (5.4, :bbb)]

```

So I’m looking for something that translates `d1` into `d2`:

```Julia
d2 = make_stable_immutable_dict(d1) # <- no idea how to do this

```

I’d be happy for any hints and ideas!

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [April 5, 2024, 2:24pm UTC](https://discourse.julialang.org/t/how-can-i-get-a-fully-specified-type-of-a-dict/112570/2 "2024-04-05T14:24:53Z")

</div>

Your first issue is gonna be that the type of your values is not fully inferred. This is an optimization sometimes done by Julia instead of dealing with weird `Union`s:

```julia
julia> [(1, "aaa"), (2.4, :bbb), (5.4, :bbb)]
3-element Vector{Tuple{Real, Any}}:
 (1, "aaa")
 (2.4, :bbb)
 (5.4, :bbb)

```

But if you solve that, broadcasting the `identity` mapping is a good way to refine type inference:

```julia
julia> x = Any[1, 2.0]
2-element Vector{Any}:
 1
 2.0

julia> identity.(x)
2-element Vector{Real}:
 1
 2.0

```

With a dictionary, here’s how it would work:

```julia
julia> Dict(identity.(keys(d1)) .=> identity.(values(d1)))
Dict{Int64, Vector} with 2 entries:
  5 => Tuple{Real, Any}[(1, "aaa"), (2.4, :bbb), (5.4, :bbb)]
  3 => [(1, "aaa"), (2, "aaa")]

```

---

<div class="post-metadata">

### Author: ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)
#### Post date: [April 5, 2024, 2:54pm UTC](https://discourse.julialang.org/t/how-can-i-get-a-fully-specified-type-of-a-dict/112570/3 "2024-04-05T14:54:03Z")

</div>

As a generalization of @gdalle’s answer, I sometimes find it useful to do this recursively:

```julia
tighten(x) = x
tighten(d::Dict) = Dict(tighten(key) => tighten(value) for (key, value) in d)
tighten(v::Vector) = tighten.(v)

```

It gives the same answer in your example:

```julia-repl
julia> d2 = tighten(d1)
Dict{Int64, Vector} with 2 entries:
  5 => Tuple{Real, Any}[(1, "aaa"), (2.4, :bbb), (5.4, :bbb)]
  3 => [(1, "aaa"), (2, "aaa")]

```

but if there were more deeply nested data structures, it could have made a difference. This is particularly useful when deserializing data from a format that loses type information, such as JSON.

---

<div class="post-metadata">

### Author: ![scheidan1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scheidan1/32/24771_2.png) [@scheidan1](https://discourse.julialang.org/u/scheidan1)
#### Post date: [April 5, 2024, 3:53pm UTC](https://discourse.julialang.org/t/how-can-i-get-a-fully-specified-type-of-a-dict/112570/4 "2024-04-05T15:53:16Z")

</div>

Thanks a lot @gdalle and @ffevotte!  
The recursive version is I exactly what would need in the real case.

Is there a way to force Julia to infer the types with `Unions`?

I can see that the would be too costly in general, but for my application the manual version with Unions is much faster.

---

<div class="post-metadata">

### Author: ![Stephen\_Vavasis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephen_vavasis/32/3389_2.png) [@Stephen\_Vavasis](https://discourse.julialang.org/u/Stephen_Vavasis)
#### Post date: [April 5, 2024, 7:34pm UTC](https://discourse.julialang.org/t/how-can-i-get-a-fully-specified-type-of-a-dict/112570/5 "2024-04-05T19:34:54Z")

</div>

If your code needs to do a lot of work for each entry of the `Dict`, then consider using a function barrier like this:

```julia
   for (k,v) in d1
      do_the_work(k,v)
   end

```

and then later

```julia
   function do_the_work(k,v)
   ...
   end

```

The main routine still needs to pay the price for deciphering the types of `k` and `v` at run-time. But `do_the_work` will get specialized and compiled separately for each different type of `k` and `v`.

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [April 5, 2024, 8:04pm UTC](https://discourse.julialang.org/t/how-can-i-get-a-fully-specified-type-of-a-dict/112570/6 "2024-04-05T20:04:27Z")

</div>

> [@scheidan1](#):
>
> Is there a way to force Julia to infer the types with `Unions`?

Open a new topic for that IMO.
