# How to distinguish an array from a tuple when doing a copy / assignment

**URL:** <https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009>\
**Category:** New to Julia\
**Created:** [May 23, 2020, 6:49am UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009 "2020-05-23T06:49:21Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![PeterB](https://avatars.discourse-cdn.com/v4/letter/p/e8c25b/32.png) [@PeterB](https://discourse.julialang.org/u/PeterB)\
**Post date:** [May 23, 2020, 6:49am UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/1 "2020-05-23T06:49:21Z")

</div>

I have a function for which one of the arguments may be either an array or a tuple, though its usage internally is tuple-like. If x is an array that then I will have the line  
`y = copy(x)`  
but if x is a tuple, copy will not work so I need to simply say:  
`y = x`  
The problem is: how can my code distinguish the two? I tried using `typeof()`, but that does not return a string, so I do not know how to interrogate the result of `typeof()`. (I looked at [Types · The Julia Language](https://docs.julialang.org/en/v1/manual/types/) but I cannot find anything there on how to process the output of `typeof()`).

EDIT: never mind, a “splat” seems to work on either:  
`y = tuple(x...)`  
EDIT 2: So I will delete this in a while unless someone asks to keep it.

---

<div class="post-metadata">

**Author:** ![tamasgal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamasgal/32/27946_2.png) [@tamasgal](https://discourse.julialang.org/u/tamasgal)\
**Post date:** [May 23, 2020, 7:37am UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/2 "2020-05-23T07:37:40Z")

</div>

You can check if it’s a subtype of a `Tuple` or equal to a specific type, like this:

```julia
julia> a = (1, 2, 3)
(1, 2, 3)

julia> typeof(a) <: Tuple
true

julia> typeof(a) == Tuple
false

julia> typeof(a)
Tuple{Int64,Int64,Int64}

julia> typeof(a) == Tuple{Int64,Int64,Int64}
true

julia> typeof(a) === Tuple{Int64,Int64,Int64}
true

julia> typeof(a) == Tuple{T, T, T} where T<:Int64
true

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 23, 2020, 7:48am UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/3 "2020-05-23T07:48:10Z")

</div>

Why do you need to copy the array? Can’t you just write `y = x` in either case? I mean, if you plan to mutate `y` that’s maybe not a good idea, but you cannot mutate tuples, so I presume that you’re not going to do that anyway.

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [May 23, 2020, 8:20am UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/4 "2020-05-23T08:20:28Z")

</div>

You could define a method of `copy` for tuples:

```julia
julia> Base.copy(t::Tuple) = t

julia> copy((1,2))
(1, 2)

```

I can’t think of a reason why this would be a bad idea, but that doesn’t mean there isn’t one!

---

<div class="post-metadata">

**Author:** ![PeterB](https://avatars.discourse-cdn.com/v4/letter/p/e8c25b/32.png) [@PeterB](https://discourse.julialang.org/u/PeterB)\
**Post date:** [May 23, 2020, 8:52am UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/5 "2020-05-23T08:52:38Z")

</div>

> [@DNF](#):
>
> Why do you need to copy the array? Can’t you just write `y = x` in either case? I mean, if you plan to mutate `y` that’s maybe not a good idea, but you cannot mutate tuples, so I presume that you’re not going to do that anyway.

Good point, I had a blind spot. I knew the following code gives nasty side effects in the calling function:

```julia
function f(x, y, some_more_params)
    if some_condition
        x[1] = y[1]
    end
    do_something
end

```

But this (which is what I wanted to do) is actually safe. My “blind spot” is that I forgot it was safe, as I was telling myself “never modify an array argument inside a function”:

```julia
function f(x, y, some_more_params)
    if some_condition
        x = y
    end
    do_something
end

```

Still, now that I have forced x to be a tuple, I feel I might as well leave it in my code, which now looks like this:

```julia
function f(x_initial, y, some_more_params)
    x = tuple(x_initial...) # a "splat" to force a tuple
    do_something
    if some_condition
        x = y
    end
    do_something
end

```

(EDIT: And in terms of readability, I think it is helpful to distinguish between the default/initial value of `x`, and the “current” value of `x`).

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 23, 2020, 11:13am UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/6 "2020-05-23T11:13:19Z")

</div>

> [@PeterB](#):
>
> I was telling myself “never modify an array argument inside a function”

There’s nothing inherently wrong with modifying an array inside a function (almost everything should be happening inside functions anyway), as long as you are deliberate about it. It’s one of the most common performance techniques. Just remember to put a `!` at the end of any function that modifies inputs, to make that clear to the caller.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 23, 2020, 11:14am UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/7 "2020-05-23T11:14:38Z")

</div>

> [@dpsanders](#):
>
> I can’t think of a reason why this would be a bad idea, but that doesn’t mean there isn’t one!

Type piracy?

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [May 23, 2020, 2:34pm UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/8 "2020-05-23T14:34:45Z")

</div>

Yes I’m aware that it’s type piracy.  
But why, for example, is `copy(t::Tuple)` not defined in Base?

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [May 23, 2020, 2:46pm UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/9 "2020-05-23T14:46:49Z")

</div>

I am not a fan of turning arrays into tuples.  
At least add a function barrier to mitigate the inevitable type instabilities.

---

<div class="post-metadata">

**Author:** ![rfourquet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rfourquet/32/3610_2.png) [@rfourquet](https://discourse.julialang.org/u/rfourquet)\
**Post date:** [May 23, 2020, 2:58pm UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/10 "2020-05-23T14:58:16Z")

</div>

> [@dpsanders](#):
>
> But why, for example, is `copy(t::Tuple)` not defined in Base?

It was defined in the past, but got removed in [remove some unncessary and/or misleading methods of `copy` by JeffBezanson · Pull Request #15675 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/15675) by Jeff:

> I think it’s better not to define `copy` on objects where it doesn’t make sense and doesn’t do anything

---

<div class="post-metadata">

**Author:** ![rfourquet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rfourquet/32/3610_2.png) [@rfourquet](https://discourse.julialang.org/u/rfourquet)\
**Post date:** [May 23, 2020, 3:22pm UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/11 "2020-05-23T15:22:53Z")

</div>

There is actually quite a number of issues/PR related to copying immutables:

- implement `copy(::Void) = nothing` ([closed PR](https://github.com/JuliaLang/julia/pull/15546), contains an interesting discussion related to “alias-stability”)

> If you have copy(f(x)), and f returning nothing is a problem, then failing in copy catches the problem sooner than having copy propagate the value. I think if some code is bothering to copy something, it’s expecting a mutable collection. (Jeff)

- Define `copy` for `Char` ([closed PR](https://github.com/JuliaLang/julia/pull/25171))
- `copy(x::Symbol)` isn’t defined ([closed issue](https://github.com/JuliaLang/julia/issues/22851))

> Generally a copy method for a (mutable) container should only copy the container structure, and not values inside. (Jeff)

- no method `copy(::Missing)` ([open issue](https://github.com/JuliaLang/julia/issues/32189))
- `copy` not implemented for `String` ([open issue](https://github.com/JuliaLang/julia/issues/31995))

> I’ve tried to avoid defining copy for immutable objects. How did this arise? My view is that code calling copy without knowing whether the argument is mutable can’t really be generic. (Jeff)

> If you’re copying something, then it must be because you’re going to mutate it—otherwise why copy it? But if some of the values are immutable, then that’s going to fail anyway, so what kind of code needs this? (Stefan)

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 23, 2020, 4:34pm UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/12 "2020-05-23T16:34:26Z")

</div>

Well you said you couldn’t think of any reason why it would be a bad idea, so I thought maybe you had a glitch and forgot it was type piracy.

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [May 23, 2020, 6:04pm UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/13 "2020-05-23T18:04:43Z")

</div>

Yes fair enough. The question is whether type piracy is always bad. I thought I remembered Jeff recently saying that it wasn’t.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 23, 2020, 6:39pm UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/14 "2020-05-23T18:39:07Z")

</div>

Yeah, I guess it’s not automatic, but it’s a red flag, I think.

---

<div class="post-metadata">

**Author:** ![tamasgal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamasgal/32/27946_2.png) [@tamasgal](https://discourse.julialang.org/u/tamasgal)\
**Post date:** [May 23, 2020, 6:56pm UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/15 "2020-05-23T18:56:48Z")

</div>

I guess it gets problematic if you e.g. put this into a library which is used by someone who finds and uses the type pirated method and doesn’t know it’s actually not in `Base`. That might cause some headaches when in another ensemble of packages this particular method is magically missing although it’s a `Base`-method dispatching on `Base`-types.

Not sure how likely this is 😉

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [May 23, 2020, 8:19pm UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/16 "2020-05-23T20:19:14Z")

</div>

I have to say that I disagree with the founders (i.e., Jeff and Stefan) on this one (what means I am probably wrong, XD). My reasoning is the following:

1. `deepcopy` is defined by default for both mutable and immutable types. What is the reasoning for having a distinct policy for `copy` and `deepcopy`? Considering that `deepcopy` can be as misleading, my first PR to a Julia library was exactly making `deepcopy` raise an exception on `JuMP.Model` because it does not copied a C pointer resource so it was not a true `deepcopy`.
2. It is just a more elegant way of doing `isimmutable(x) || (x = copy(x))` or `y = isimmutable(x) ? x : copy(x)`.
3. As pointed by (2) it is just a matter of convenience, not defining `copy` will do little but make programmer scratch their head and sometimes they will be happy that some bug did not propagate, others they will just lose some time thinking if it is better to put an `if`, or define `copy` for some immutable type, or just change statement order, and if they did assume wrong that copy would not raise exception over immutable types and now they need to check their code for it.
4. As `copy` is not defined for default for immutable types _but also is not guaranteed to not be defined for immutable types_, programmers cannot assume that arbitrary immutable types in the wild will or not provide them.
5. Programmer making use of type piracy to ‘inoffensively’ create `copy` methods for convenience can change the error that is raised in some situation, making harder to identify that is the same problem as others had.
6. The current state is not completely coherent either, `Int`, `Float64`, and others have `copy` defined even being immutable types (and will raise different errors when passed to a method that often throws on `copy` for arbitrary immutable types).

Again, not the strongest case, but I feel like it was just a bit more convenient if `copy` and `deepcopy` had the same policy. Not the sufficient, probably, for meriting the change now they are already this way.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [May 24, 2020, 4:50am UTC](https://discourse.julialang.org/t/how-to-distinguish-an-array-from-a-tuple-when-doing-a-copy-assignment/40009/17 "2020-05-24T04:50:57Z")

</div>

> [@PeterB](#):
>
> `x = tuple(x_initial...)`

I wouldn’t recommend this for code where you care about performance, as it will be slow both for arrays and for longer tuples.

This code will perform badly for arrays because the output type depends on the number of elements of the array, so the compiler won’t generally be able to figure out the type of `x`. And it will perform badly for long tuples because splatting large numbers of arguments (more than I think 16) will generate less efficient code. That’s due to an intentional trade off in the compiler to avoid spending a long time generating code for functions with huge numbers of arguments.

As you’ve already discovered, doing `x = y` seems to be totally fine for your use case, and it will perform better too. So I’d recommend just doing that 🙂
