# copy(::CartesianIndices)

**URL:** <https://discourse.julialang.org/t/copy-cartesianindices/45818>\
**Category:** General Usage\
**Tags:** indexing\
**Created:** [August 31, 2020, 7:32am UTC](https://discourse.julialang.org/t/copy-cartesianindices/45818 "2020-08-31T07:32:15Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![greg\_plowman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/greg_plowman/32/8100_2.png) [@greg\_plowman](https://discourse.julialang.org/u/greg_plowman)\
**Post date:** [August 31, 2020, 7:32am UTC](https://discourse.julialang.org/t/copy-cartesianindices/45818/1 "2020-08-31T07:32:15Z")

</div>

`copy(x::CartesianIndices)` and `copy(x::LinearIndices)` do not return the same type as the input argument.

I guess you could argue that it doesn’t make sense to copy an immutable. But perhaps you could also argue that trying to copy an immutable should either return the correct type or result in a “no matching method” error.

There is a precedent for defining `copy` for immutables. Here’s a definition for copying ranges from Base:

```julia
# Ranges are immutable
copy(r::AbstractRange) = r

```

So let’s try copying `CartesianIndices` and `LinearIndices`

```julia
dims = ntuple(d -> -1:1, 2)
CIs = CartesianIndices(dims)
LIs = LinearIndices(CIs)

```

```julia
julia> copy(CIs)
3×3 Array{CartesianIndex{2},2}:
 CartesianIndex(-1, -1) CartesianIndex(-1, 0) CartesianIndex(-1, 1)
 CartesianIndex(0, -1) CartesianIndex(0, 0) CartesianIndex(0, 1)
 CartesianIndex(1, -1) CartesianIndex(1, 0) CartesianIndex(1, 1)

julia> copy(LIs)
3×3 Array{Int64,2}:
 1 4 7
 2 5 8
 3 6 9

```

The fallback for `copy` seems to go through `similar` which returns an `Array` for these types.

For non-standard indexing, an `OffsetArray` is returned (if `OffsetArrays` are in scope, otherwise there’s a no method matching error).

> **Summary**
>
> ```julia
> dims = ntuple(d -> -1:1, 2)
> CIs = CartesianIndices(Base.IdentityUnitRange.(dims))
> LIs = LinearIndices(CIs)
> 
> ```
> 
> ```julia
> julia> copy(CIs)
> ERROR: MethodError: no method matching similar(::CartesianIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}, ::Type{CartesianIndex{2}}, ::Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}})
> Closest candidates are:
> similar(::AbstractArray, ::Type{T}) where T at abstractarray.jl:629
> similar(::AbstractArray, ::Type{T}, ::Union{Integer, AbstractUnitRange}...) where T at abstractarray.jl:632
> similar(::AbstractArray, ::Type{T}, ::Tuple{Vararg{Int64,N}}) where {T, N} at abstractarray.jl:640
> ...
> Stacktrace:
> [1] similar(::CartesianIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}, ::Type{CartesianIndex{2}}) at .\abstractarray.jl:629
> [2] similar(::CartesianIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}) at .\abstractarray.jl:628
> [3] copymutable at .\abstractarray.jl:971 [inlined]
> [4] copy(::CartesianIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}) at .\abstractarray.jl:915
> [5] top-level scope at REPL[4]:1
> 
> julia> copy(LIs)
> ERROR: MethodError: no method matching similar(::LinearIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}, ::Type{Int64}, ::Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}})
> Closest candidates are:
> similar(::AbstractArray, ::Type{T}) where T at abstractarray.jl:629
> similar(::AbstractArray, ::Type{T}, ::Union{Integer, AbstractUnitRange}...) where T at abstractarray.jl:632
> similar(::AbstractArray, ::Type{T}, ::Tuple{Vararg{Int64,N}}) where {T, N} at abstractarray.jl:640
> ...
> Stacktrace:
> [1] similar(::LinearIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}, ::Type{Int64}) at .\abstractarray.jl:629
> [2] similar(::LinearIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}) at .\abstractarray.jl:628
> [3] copymutable at .\abstractarray.jl:971 [inlined]
> [4] copy(::LinearIndices{2,Tuple{Base.IdentityUnitRange{UnitRange{Int64}},Base.IdentityUnitRange{UnitRange{Int64}}}}) at .\abstractarray.jl:915
> [5] top-level scope at REPL[5]:1
> 
> ```

Would it make sense to define the following `copy` methods?

```julia
Base.copy(x::CartesianIndices) = x
Base.copy(x::LinearIndices) = x

```

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [August 31, 2020, 7:43am UTC](https://discourse.julialang.org/t/copy-cartesianindices/45818/2 "2020-08-31T07:43:26Z")

</div>

My opinion is that `copy(x) = x` is the right thing for immutables. While it is a useless operation if you know that `x` is immutable, it can be useful in generic code. I think it would be nice to just open a PR to julialang/julia with the proposed change.

---

<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:** [August 31, 2020, 9:03am UTC](https://discourse.julialang.org/t/copy-cartesianindices/45818/3 "2020-08-31T09:03:19Z")

</div>

> [@jw3126](#):
>
> While it is a useless operation if you know that `x` is immutable, it can be useful in generic code.

Why is it useful for generic code? The reason you `copy` is so that you will mutate it later, which will fail for immutables anyway?

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [August 31, 2020, 9:05am UTC](https://discourse.julialang.org/t/copy-cartesianindices/45818/4 "2020-08-31T09:05:15Z")

</div>

> ```
> Why is it useful for generic code? The reason you copy is so that you will mutate it later, which will fail for immutables anyway?
> 
> ```

Or that you want a snapshot of the current version that does not change if the original is mutated.

---

<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:** [August 31, 2020, 9:08am UTC](https://discourse.julialang.org/t/copy-cartesianindices/45818/5 "2020-08-31T09:08:22Z")

</div>

Almost feels like `deepcopy` is better then.

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [August 31, 2020, 9:14am UTC](https://discourse.julialang.org/t/copy-cartesianindices/45818/6 "2020-08-31T09:14:07Z")

</div>

I tend to agree. However I still think relying on copy to return something mutable is a bad idea. E.g. it fails for ranges right now. Also `typeof(copy(x)) != typeof(x)` is a surprise. I think if you want a mutable copy, then you should be explicit about it. Anyway if people are using copy like this, then it is not worth breaking their code. But maybe `copy` docs could be clarified about semantics, e.g. `typeof(copy(x)) != typeof(x)` and mutability.

---

<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:** [August 31, 2020, 2:27pm UTC](https://discourse.julialang.org/t/copy-cartesianindices/45818/7 "2020-08-31T14:27:09Z")

</div>

> [@jw3126](#):
>
> However I still think relying on copy to return something mutable is a bad idea.

Yes, this is incorrect. The function that `Base` uses when it needs a mutable copy is `Base.copymutable` (added here: [fix and consolidate uses of copy(a) and copy(similar(a),a) in to copymutable(a) by stevengj · Pull Request #16620 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/16620)). Maybe it’s time to finally export that function?

Alternatively, `similar` is guaranteed to return a mutable type, so you could use `copy!(similar(a),a)` (at least for arrays — this doesn’t work for generic iterables)… encapsulating that common pattern was precisely why `copymutable` was added.

> [@kristoffer.carlsson](#):
>
> The reason you `copy` is so that you will mutate it later

No:

```julia
julia> copy(1:10)
1:10

```

I agree with @greg_plowman that copying `CartesianIndices` or `LinearIndices` should act like copying ranges.

---

<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:** [August 31, 2020, 2:35pm UTC](https://discourse.julialang.org/t/copy-cartesianindices/45818/8 "2020-08-31T14:35:13Z")

</div>

> [@stevengj](#):
>
> No:
> 
> ```julia
> julia> copy(1:10)
> 1:10
> 
> ```

I think you need to elaborate a bit. That looked pointless to me.

---

<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:** [August 31, 2020, 2:50pm UTC](https://discourse.julialang.org/t/copy-cartesianindices/45818/9 "2020-08-31T14:50:56Z")

</div>

> [@kristoffer.carlsson](#):
>
> That looked pointless to me.

Pointless or not, it’s behaved that way for years and it probably can’t be changed before Julia 2.0. `copy` does not guarantee a mutable result, so assuming that property is wrong.

---

<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:** [August 31, 2020, 2:56pm UTC](https://discourse.julialang.org/t/copy-cartesianindices/45818/10 "2020-08-31T14:56:42Z")

</div>

> [@stevengj](#):
>
> `copy` does not guarantee a mutable result, so assuming that property is wrong.

I know it doesn’t guarantee that and I never said that it did. I said that the reason why you want to copy something is because you want to mutate it later. The fact that there are some pointless `copy` methods defined for various types doesn’t change that.

---

<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:** [August 31, 2020, 5:48pm UTC](https://discourse.julialang.org/t/copy-cartesianindices/45818/11 "2020-08-31T17:48:58Z")

</div>

> [@kristoffer.carlsson](#):
>
> I said that the reason why you want to copy something is because you want to mutate it later.

Are you referring to `copy` and `deepcopy` or just `copy`? Because some generic code may need to keep an user-provided object in a way that it is sure it will not be changed externally. In this case, the code does not change the object, nor assume it is mutable, but keeps a `deepcopy` of it because it _may_ be mutable.
