# Unexpected copy when pushing

**URL:** <https://discourse.julialang.org/t/unexpected-copy-when-pushing/21495>\
**Category:** New to Julia\
**Created:** [March 5, 2019, 2:59pm UTC](https://discourse.julialang.org/t/unexpected-copy-when-pushing/21495 "2019-03-05T14:59:43Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![jbaxter](https://avatars.discourse-cdn.com/v4/letter/j/7993a0/32.png) [@jbaxter](https://discourse.julialang.org/u/jbaxter)\
**Post date:** [March 5, 2019, 2:59pm UTC](https://discourse.julialang.org/t/unexpected-copy-when-pushing/21495/1 "2019-03-05T14:59:44Z")

</div>

Hello, I’m a very early beginner. I wanted to have an array of dictionaries. Simple example below. It seems that when I push a dictionary which does not exactly match the type of array, instead of, say, getting a complaint from the compiler, the dictionary is _copied_. Fine, but naturally one would like to know when this will happen, better approach, etc. Thanks for any help!  
(As part of learning I’m trying to declare most types explicitly for now.)

```julia
a = Dict{String, Union{Int64, Nothing}}[]
x = Dict("wet"=>1)
push!(a, x)
x["dry"]= 2
println("x == a[1] is now "* string(x == a[1])) #it's false, and keys are different
y = Dict{String, Int64}("fish"=>3)
push!(a,y)
y["fowl"]=4
println("y == a[2] is now "* string(y == a[2])) #it's false, and keys are different
z = Dict{String, Union{Int64, Nothing}}("hot"=>4)
push!(a,z)
z["cold"]=5
println("z == a[3] is now still "* string(z == a[3])) # it's true.

```

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [March 5, 2019, 3:14pm UTC](https://discourse.julialang.org/t/unexpected-copy-when-pushing/21495/2 "2019-03-05T15:14:49Z")

</div>

Please quote your code (you can edit your post), and perhaps don’t make all text bold, it is a distraction.

> [@PSA: how to quote code with backticks](https://discourse.julialang.org/t/psa-how-to-quote-code-with-backticks/7530):
>
> This is a short post on how to use backticks (` and ```) to quote code, so it is easy to read. This post can be linked to new users who are confused by this feature. Why By quoting your code, you get a monospaced font (which preserves indentation) and syntax highlighting. This makes it easier to read your code and help you. Displayed code looks like this: function displayed\_code(x::Int, y::Int) if x \< y println("x is smaller") else println("or not") end end Inline…

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [March 5, 2019, 4:00pm UTC](https://discourse.julialang.org/t/unexpected-copy-when-pushing/21495/3 "2019-03-05T16:00:21Z")

</div>

I’ve gone ahead and quoted @jbaxter’s code since otherwise it was impossible to cut and paste into a REPL to try to help answer the question.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [March 5, 2019, 4:07pm UTC](https://discourse.julialang.org/t/unexpected-copy-when-pushing/21495/4 "2019-03-05T16:07:19Z")

</div>

The key issue is that `Dict{String, Union{Int, Nothing}}` and `Dict{String, Int}` are different, disjoint types. In order to put a `Dict{String, Int}` value into an array with element type `Dict{String, Union{Int, Nothing}}` it must be converted to a value of the correct type, which means copying it. If you typed your array like this then no conversion would be required:

```julia
a = Dict{String, <:Union{Int64, Nothing}}[]

```

However, I should mention that once you get to such loosely typed abstract collections, it’s harder on the compiler to generate specialized code and unless you really want to make sure nobody puts the wrong type of value in there, you’re better off just using an `Any`-typed array, i.e. just:

```julia
a = []

```

This has the same array-of-pointers representation anyway and already has all the code one might need generated for it, as opposed to `Vector{Dict{String, <:Union{Int64, Nothing}}}` which is a new type that’s likely to need all new code generated for it.

---

<div class="post-metadata">

**Author:** ![yha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yha/32/3502_2.png) [@yha](https://discourse.julialang.org/u/yha)\
**Post date:** [March 5, 2019, 4:35pm UTC](https://discourse.julialang.org/t/unexpected-copy-when-pushing/21495/5 "2019-03-05T16:35:45Z")

</div>

A tangential point: debug prints like these

> [@jbaxter](#):
>
> println("x == a[1] is now "\* string(x == a[1]))

can be easier with the `@show` macro, which saves you the trouble of writing the expression again inside a string literal.

---

<div class="post-metadata">

**Author:** ![jbaxter](https://avatars.discourse-cdn.com/v4/letter/j/7993a0/32.png) [@jbaxter](https://discourse.julialang.org/u/jbaxter)\
**Post date:** [March 5, 2019, 5:20pm UTC](https://discourse.julialang.org/t/unexpected-copy-when-pushing/21495/6 "2019-03-05T17:20:30Z")

</div>

thanks for all these points! Fewer explicit types seems to be best for me.

---

<div class="post-metadata">

**Author:** ![jbaxter](https://avatars.discourse-cdn.com/v4/letter/j/7993a0/32.png) [@jbaxter](https://discourse.julialang.org/u/jbaxter)\
**Post date:** [March 6, 2019, 3:27pm UTC](https://discourse.julialang.org/t/unexpected-copy-when-pushing/21495/7 "2019-03-06T15:27:18Z")

</div>

I’m trying now to take a general lesson from this example, to help write correct programs in the future. I know Julia uses pass by sharing, but something else is evidently involved here. Is there a general rule about when Julia makes a _copy_ of a mutable value instead of passing a reference, or issuing an error message? (Or likely a section of the documentation I should read to understand this particular issue!)  
I understand that, as was stated, the copying takes place to match the type. But I suppose the passed type has to be close in some sense to the correct one or Julia would warn me of my mistake.  
Thanks again.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [March 6, 2019, 4:37pm UTC](https://discourse.julialang.org/t/unexpected-copy-when-pushing/21495/8 "2019-03-06T16:37:36Z")

</div>

> [@jbaxter](#):
>
> I know Julia uses pass by sharing

No. For immutables, it is actually _undefined_ what happens under the hood, when the user can’t tell the difference. This gives the compiler room for optimizations, see eg [a recent discussion](https://discourse.julialang.org/t/how-are-called-in-julia-terminology-int64-float64-vs-array-t-1-tuple-t1-t2-set-t/21006/6).

> [@jbaxter](#):
>
> Is there a general rule about when Julia makes a _copy_ of a mutable value instead of passing a reference

I think that the general rule in `Base` and the standard library is that things are never copied implicitly, but _converted_ when necessary. See

[https://docs.julialang.org/en/v1/manual/conversion-and-promotion/#When-is-convert-called?-1](https://docs.julialang.org/en/v1/manual/conversion-and-promotion/#When-is-convert-called?-1)

---

<div class="post-metadata">

**Author:** ![jbaxter](https://avatars.discourse-cdn.com/v4/letter/j/7993a0/32.png) [@jbaxter](https://discourse.julialang.org/u/jbaxter)\
**Post date:** [March 6, 2019, 5:09pm UTC](https://discourse.julialang.org/t/unexpected-copy-when-pushing/21495/9 "2019-03-06T17:09:20Z")

</div>

That is very helpful. I read some of the linked manual section, especially “conversion versus construction”. For me the key point was not whether the operation is called “copying”, but whether a new object is created, as in my example it seems to be. In the manual it says that since `convert` can be called implicitly, its methods are restricted to cases that are considered “safe” or “unsurprising”. I have to admit that I was surprised to find that updating the mutable object I pushed made no difference to the object I had appended to the array. However, I am sure there are good reasons for this behavior. Anyway I will keep the link you provided handy and try to be careful (being careful is not easy for me 😣). Thanks again.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [March 6, 2019, 5:43pm UTC](https://discourse.julialang.org/t/unexpected-copy-when-pushing/21495/10 "2019-03-06T17:43:45Z")

</div>

Implicit conversion of mutable types is a bit dangerous since it amounts to implicit copying. Can’t be changed now but worth keeping in mind for Julia 2.0. Then again people love the convenience of implicit conversion based on types locations, especially since Julia is very careful about conversions that don’t preserve value.
