# How exactly is deepcopy defined?

**URL:** <https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445>\
**Category:** General Usage\
**Tags:** deepcopy\
**Created:** [October 15, 2017, 7:37am UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445 "2017-10-15T07:37:05Z")\
**Posts on this page:** 13\
**Page:** 1

<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:** [October 15, 2017, 7:37am UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445/1 "2017-10-15T07:37:06Z")

</div>

Observe the following:

```julia
julia> a = [8,7,6]
3-element Array{Int64,1}:
 8
 7
 6
julia> b = [a,a]
2-element Array{Array{Int64,1},1}:
 [8, 7, 6]
 [8, 7, 6]
julia> c=deepcopy(b)
2-element Array{Array{Int64,1},1}:
 [8, 7, 6]
 [8, 7, 6]
julia> c[1][1] = 9
9
julia> c
2-element Array{Array{Int64,1},1}:
 [9, 7, 6]
 [9, 7, 6]

```

So the point of this example is: The output `c` of `deepcopy` still contains two arrays that are actually the same object. This seems to contradict the documentation, which says that the copying continues recursively until the leaves are reached. If the above example is the intended behavior of `deepcopy`, could someone give a precise definition of its functionality?

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [October 15, 2017, 9:39am UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445/2 "2017-10-15T09:39:41Z")

</div>

Whether the documentation is confusing depends on what you think “copy” means; in this case `deepcopy` deliberately goes to some effort to do what you observed. In the [source code](https://github.com/JuliaLang/julia/blob/master/base/deepcopy.jl) the `ObjectIdDict` is precisely to make sure that references are preserved as references; the source is not very long and reasonably straightforward, so if you have specific questions I’d urge you to check it first. If you think the docstring could be further clarified, a PR (or at least an edited text posted here) would be great!

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [October 15, 2017, 12:14pm UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445/3 "2017-10-15T12:14:29Z")

</div>

It would be weird if the deepcopied object didn’t behave as the original one. I’m not sure that could even be called a copy.

---

<div class="post-metadata">

**Author:** ![smldis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/smldis/32/1735_2.png) [@smldis](https://discourse.julialang.org/u/smldis)\
**Post date:** [October 15, 2017, 12:52pm UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445/4 "2017-10-15T12:52:33Z")

</div>

On the docs:

```julia
"""
    deepcopy(x)
Create a deep copy of `x`: everything is copied recursively, resulting in a fully
independent object. For example, deep-copying an array produces a new array whose elements
are deep copies of the original elements.
"""

```

- Defining the deepcopy function with “Create a deep copy…” seems bad (Is there a proper def in the docs?)
- On “Everything is copied rec…”, the world everything doesn’t tell me anything.

Maybe someone can help with my proposal (I hope mine is at least a start):

```julia
"""
Instantiate a variable of the same type of x and proceed recursively through the fields of x. 
The leaves values are copied to new instances and all the references inside the output variable
point to these new instances.
"""

```

---

<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:** [October 15, 2017, 1:12pm UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445/5 "2017-10-15T13:12:43Z")

</div>

> [@smldis](#):
>
> world everything doesn’t tell me anything

I think that this is pretty clear: “everything” in this context is “all elements in a container”.

Regarding your proposed docstring: not all containers have fields, eg consider arrays.

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [October 15, 2017, 1:46pm UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445/6 "2017-10-15T13:46:25Z")

</div>

Perhaps the documentation could be clearer, but the behaviour makes sense (and has precedent in other languages). Without it, deep-copying structures with cycles (eg. doubly-linked lists) would never complete. And an array of 100 views into another array X would create 100 copies of X.

---

<div class="post-metadata">

**Author:** ![smldis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/smldis/32/1735_2.png) [@smldis](https://discourse.julialang.org/u/smldis)\
**Post date:** [October 15, 2017, 1:48pm UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445/7 "2017-10-15T13:48:00Z")

</div>

Right, I forgot the main part.

> [@Tamas\_Papp](#):
>
> I think that this is pretty clear: “everything” in this context is “all elements in a container”.

Is the word “container” defined in the docs? I am not able to understand your explanation of everything.  
Maybe it depends on the leaf type itself. The implementation of deepcopy\_internal of the leaftype is called and that’s where “everything” is define.

> [@Tamas\_Papp](#):
>
> Regarding your proposed docstring: not all containers have fields, eg consider arrays.

Wait, all types have a number of fields, sometimes this number is zero. Additionally elements of arrays are copied because of the `deepcopy_internal method` for `Array`s (Is there something also for `AbstractArray`s?)

There could be a statement that suggest that for “containers” (to be defined) there is a common practice of propagating through the elements the recursive action.

Thanks for the correction

---

<div class="post-metadata">

**Author:** ![smldis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/smldis/32/1735_2.png) [@smldis](https://discourse.julialang.org/u/smldis)\
**Post date:** [October 15, 2017, 2:03pm UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445/8 "2017-10-15T14:03:42Z")

</div>

For reference, i found also the definition of deepcopy in `DataStructures.jl` for sorted containers.

```julia
"""
deepcopy(sc)
This returns a copy of sc in which the data is deep-copied, i.e., the keys and values are replicated if they are mutable types. A semitoken for the original sc is a valid semitoken for the copy because this operation preserves the relative positions of the data in memory. Time O(maxn), where maxn denotes the maximum size that sc has attained in the past.
"""

```

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [October 15, 2017, 2:10pm UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445/9 "2017-10-15T14:10:24Z")

</div>

How about

```julia
"""
    deepcopy(x)
Create a deep copy of `x`: everything is copied recursively, where every node is visited only once, 
resulting in a fully independent object of the same internal structure as the input object. For example, 
deep-copying an array produces a new array whose elements are deep copies of the original elements, 
and deep-copying an array of views of the same data array only copies the data array once.
"""

```

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [October 15, 2017, 3:30pm UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445/10 "2017-10-15T15:30:48Z")

</div>

How about just add the OP’s code as an example with an enlightening explanation. A good example is better than thousand words 😉

---

<div class="post-metadata">

**Author:** ![foobar\_lv](https://avatars.discourse-cdn.com/v4/letter/f/35a633/32.png) [@foobar\_lv](https://discourse.julialang.org/u/foobar_lv)\
**Post date:** [October 15, 2017, 9:03pm UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445/11 "2017-10-15T21:03:24Z")

</div>

How about adding to the description

```julia
"""This is roughly equivalent to serializing, and then unserializing an object. 
Deepcopy respects object identity (===).
 (python analog: deepcopy = lambda x: pickle.loads(pickle.dumps(x));
there can be no generic C/C++ analog) """

```

Maybe one should also add something about failure modes for types that are bad for deepcopying because they hold external references (e.g. pointers, os resources, filehandles)? Maybe one should describe how finalizers and object references in closures of finalizers are handled?

I cannot say, since I honestly don’t know how deepcopy handles these cases.

---

<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:** [October 16, 2017, 8:34am UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445/12 "2017-10-16T08:34:23Z")

</div>

> [@foobar\_lv](#):
>
> I cannot say, since I honestly don’t know how deepcopy handles these cases.

You can always read the source:

```julia
julia> io = open("/tmp/test", "w")
IOStream(<file /tmp/test>)

julia> @edit deepcopy(io)

```

Examples/concepts from another language may not be a good idea: it is better to explain concepts than rely on the reader’s knowledge of Python.

---

<div class="post-metadata">

**Author:** ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)\
**Post date:** [December 4, 2024, 10:58am UTC](https://discourse.julialang.org/t/how-exactly-is-deepcopy-defined/6445/13 "2024-12-04T10:58:47Z")

</div>

There’s a relatively simple explanation to why this is the case, but it hasn’t been explicitly stated.

Your object `a` is a vector containing 3 integers.

`b` is a vector containing two references to `a`. That’s the same reference to `a`, twice.

`deepcopy` produces an exact clone of an object (presumably) by recursively calling `deepcopy` on each sub-element of an object.

In this case, you `deepcopy(b)`, which produces a vector containing the same data a `b` does, which is two references to `a`.

If `deepcopy` were to change references into copies of the underlying object, that would be surprising and hard for the programmer to understand.

In this case I think your confusion has come from the way in which Julia has printed data to your terminal window. It looks like `b` is a 2d matrix, but it is not.
