# Which copy function should I overload?

**URL:** <https://discourse.julialang.org/t/which-copy-function-should-i-overload/129595>\
**Category:** General Usage\
**Tags:** copy, deepcopy\
**Created:** [June 3, 2025, 10:25am UTC](https://discourse.julialang.org/t/which-copy-function-should-i-overload/129595 "2025-06-03T10:25:53Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![mhauru](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mhauru/32/208880_2.png) [@mhauru](https://discourse.julialang.org/u/mhauru)\
**Post date:** [June 3, 2025, 10:25am UTC](https://discourse.julialang.org/t/which-copy-function-should-i-overload/129595/1 "2025-06-03T10:25:53Z")

</div>

I have an abstract type, call it `Abe`, subtypes of which may or may not be mutable. I want a function that I can call on `Abe`s that will make a (deepish) copy of the ones that are mutable (or in some cases wrap objects that are mutable) and do nothing for the immutable ones. The goal is to be able to do things like `do_thing!!(copy(a::Abe))` when I want to make sure `a` isn’t modified by some operation `do_thing!!` that might make use of the mutability of some of the subtypes.

Which copy function should I use for this? [According to Jeff](https://github.com/JuliaLang/julia/issues/42796#issuecomment-951232853), `deepcopy` is dangerous and you should avoid it like a semi-serious contagious disease. However, [also according to Jeff](https://github.com/JuliaLang/julia/issues/45143), one shouldn’t define methods of `copy` for immutable types. The docstring also explicitly says `copy` is shallow, and I would like to violate that for some of my types that e.g. wrap an `Array`. However, defining my very own `mycopy` function seems quite silly, when really what I want to implement is just the natural meaning of copying for my types. What do?

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [June 3, 2025, 2:35pm UTC](https://discourse.julialang.org/t/which-copy-function-should-i-overload/129595/2 "2025-06-03T14:35:52Z")

</div>

I’m not sure that this is the most idiomatic (though I never fully understood the harm of a no-op `copy` for inapplicable types, so I can’t say that I’m avoiding the true issue with my following suggestion), but my workaround has been to define my own `maybecopy` function that will call `copy` for applicable types but not others. It’s not _that_ silly. You can support this with a trait.

```julia
# Set the default to true or false, as convenient.
# An advantage of defaulting to `true` is that it will try to copy a type and
# if it throws a MethodError you can add it to the list of exceptions.
cancopy(::Any) = true

# list of exceptions
cancopy(::MyUncopyableType) = false

# copy or don't, depending on `cancopy`
maybecopy(x) = cancopy(x) ? copy(x) : x

```

Getting less idiomatic: instead of the trait you could use `hasmethod` or `applicable`, but I recall a few types that define `copy` methods just to throw errors which then still require special-casing. Further, introspection of method tables is highly discouraged in most situations.

As for `deepcopy`, it is allegedly dangerous and is appallingly slow. I think most other schemes you could concoct will ultimately be better than it.

---

<div class="post-metadata">

**Author:** ![TimG](https://avatars.discourse-cdn.com/v4/letter/t/82dd89/32.png) [@TimG](https://discourse.julialang.org/u/TimG)\
**Post date:** [June 3, 2025, 5:36pm UTC](https://discourse.julialang.org/t/which-copy-function-should-i-overload/129595/3 "2025-06-03T17:36:22Z")

</div>

I [recently](https://discourse.julialang.org/t/reliably-make-a-clean-copy-of-an-xml-node/129495/5) defined a `copy` method for an XML.jl `Node`. I thought I was doing the right thing to avoid `deepcopy`.

`Node`s in XML.jl are immutable but they may contain some mutable elements, one of which may be a set of nested vectors of child `Nodes`. To copy a `Node`, it is also necessary to copy all it’s children. So my `copy` is not shallow.

I am working with XML to manipulate Excel `.xlsx` files. I have a library of `Node`s in a `Dict` to provide a set of common Excel features and these each includes nested child `Node`s. To add one to an `xlsx` file, I copy the `Node` from the library and then insert it into the internal XML structure of the `xlsx` file.

I can call the function I use to make a duplicate of the `Node` in the library anything I want, but functionally, I am making a copy. Is this to be frowned upon? And if so, what should I do instead? Just rename the function?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 3, 2025, 10:18pm UTC](https://discourse.julialang.org/t/which-copy-function-should-i-overload/129595/4 "2025-06-03T22:18:28Z")

</div>

> [@mhauru](#):
>
> However, [also according to Jeff](https://github.com/JuliaLang/julia/issues/45143), one shouldn’t define methods of `copy` for immutable types.

I interpreted that thread as that `copy` is fine for immutable types with mutation API (and don’t necessarily output the same type), and those without mutation API don’t have a reason to fall back to an `identity`-like result because you can’t mutate them to begin with. Since `copy` and `deepcopy` really only show up in code that does mutation, an implementation would only delay an error. There were exceptions listed across the links, so we can actually make an example:

```julia
julia> setindex!(copy([1,2,3]), 10, 1) # mutable type, copies to new array
3-element Vector{Int64}:
 10
  2
  3

julia> setindex!(copy(view([1,2,3], 1:2:3)), 10, 1) # immutable type with mutation API, copies to Array
2-element Vector{Int64}:
 10
  3

julia> setindex!(copy(1:3), 10, 1) # immutable type, identity-like copy
ERROR: CanonicalIndexError: setindex! not defined for UnitRange{Int64}

```

> [@mhauru](#):
>
> The docstring also explicitly says `copy` is shallow, and I would like to violate that for some of my types that e.g. wrap an `Array` . However, defining my very own `mycopy` function seems quite silly

`copy` is strictly shallow, you shouldn’t defy API. Why not a `Abe` constructor that takes instances of `Abe` subtypes? No need to make it shallow or deep, just instantiate as you like.

---

<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:** [June 4, 2025, 10:58am UTC](https://discourse.julialang.org/t/which-copy-function-should-i-overload/129595/5 "2025-06-04T10:58:52Z")

</div>

> [@mhauru](#):
>
> The goal is to be able to do things like `do_thing!!(copy(a::Abe))` when I want to make sure `a` isn’t modified by some operation `do_thing!!` that might make use of the mutability of some of the subtypes.

Why not specialize `do_thing!!` or its internals instead? How is it that your code could work for both mutables and immutables?

From the discussions you linked, the motivation for not having a no-op `copy` for immutables is that if you are asking for a copy, your intention is probably to modify the result. There is no other use case I am aware of.

---

<div class="post-metadata">

**Author:** ![TimG](https://avatars.discourse-cdn.com/v4/letter/t/82dd89/32.png) [@TimG](https://discourse.julialang.org/u/TimG)\
**Post date:** [June 4, 2025, 12:48pm UTC](https://discourse.julialang.org/t/which-copy-function-should-i-overload/129595/6 "2025-06-04T12:48:21Z")

</div>

> [@Benny](#):
>
> No need to make it shallow or deep, just instantiate as you like.

I don’t think I understand the difference between instantiating a new thing that is identical to an old thing versus copying the old thing. Not implying there isn’t a difference - just that I don’t know what it is.

Is it about piracy?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 4, 2025, 6:57pm UTC](https://discourse.julialang.org/t/which-copy-function-should-i-overload/129595/7 "2025-06-04T18:57:04Z")

</div>

You’re strictly implementing methods annotated with your defined types, so there’s no piracy going on. The issue is API

- `Base.copy` is strictly shallow, `Base.deepcopy` is strictly deep, you want “deepish” so that’s a good indication you’re dealing with a different function entirely. If it’s the name you’re attached to, you can even make a `AbeModule.copy`, though it’d be annoying to disambiguate that from `Base.copy` if you or another user ever need it.
- `Base.copy`-ing doesn’t make an identical instance (semantically that would be the SAME instance, `===`), nor does it guarantee an output instance of the same type as the input (see the earlier example where a view gets copied into a `Vector`). It just guarantees the outmost layer of _semantic elements_ are identical. If you want a guarantee of `T` in `T` out, then you need to make your own API, whether it’s a new function or repurposing a constructor.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [June 4, 2025, 7:42pm UTC](https://discourse.julialang.org/t/which-copy-function-should-i-overload/129595/8 "2025-06-04T19:42:18Z")

</div>

Can you explain why you want to copy an immutable object? In general it’s not useful to copy something unless you’re going to mutate the in- or out-argument, which you can’t do to an immutable object.

I wouldn’t use `deepcopy` though.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [June 4, 2025, 7:44pm UTC](https://discourse.julialang.org/t/which-copy-function-should-i-overload/129595/9 "2025-06-04T19:44:37Z")

</div>

> [@mhauru](#):
>
> However, [also according to Jeff](https://github.com/JuliaLang/julia/issues/45143), one shouldn’t define methods of `copy` for immutable types.

If it might be mutable (even via mutable fields), I would just define `copy`.

For example, both `SubArray` and `LinearAlgebra.Adjoint` are immutable types that can wrap a mutable `Array` object, and both define methods like `setindex!` that allow you to mutate the underlying array. Both of them define `copy` methods when they wrap a mutable array.

---

<div class="post-metadata">

**Author:** ![TimG](https://avatars.discourse-cdn.com/v4/letter/t/82dd89/32.png) [@TimG](https://discourse.julialang.org/u/TimG)\
**Post date:** [June 5, 2025, 7:42am UTC](https://discourse.julialang.org/t/which-copy-function-should-i-overload/129595/10 "2025-06-05T07:42:26Z")

</div>

> [@TimG](#):
>
> I am working with XML to manipulate Excel `.xlsx` files. I have a library of `Node`s in a `Dict` to provide a set of common Excel features and these each includes nested child `Node`s. To add one to an `xlsx` file, I copy the `Node` from the library and then insert it into the internal XML structure of the `xlsx` file.

In my case, I may or may not want to make changes as I copy, depending on the user supplied `kw`s.

I don’t have any problem using a name other than `Base.copy`. I had thought `Base.copy` was a good choice but, thanks to this thread and especially to @Benny, I now know better.
