# Unpacking CartesianIndex

**URL:** <https://discourse.julialang.org/t/unpacking-cartesianindex/27374>\
**Category:** General Usage\
**Tags:** indexing\
**Created:** [August 10, 2019, 3:30am UTC](https://discourse.julialang.org/t/unpacking-cartesianindex/27374 "2019-08-10T03:30:37Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Charlie\_He](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/charlie_he/32/9465_2.png) [@Charlie\_He](https://discourse.julialang.org/u/Charlie_He)\
**Post date:** [August 10, 2019, 3:30am UTC](https://discourse.julialang.org/t/unpacking-cartesianindex/27374/1 "2019-08-10T03:30:37Z")

</div>

```julia
for (i, j) in CartesianIndices(a)
    println(i, j)
end

```

produces an error:

```julia
ERROR: iteration is deliberately unsupported for CartesianIndex. Use `I` rather than `I...`, or use `Tuple(I)...`

```

This is an unreasonable design of the Julia interface in my opinion, which implements unpacking using iterator. I suggest Julia have an additional function `unpack` which is called when unpacking syntax is used and only falls back to `iterate` by default.

---

<div class="post-metadata">

**Author:** ![tianrluo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tianrluo/32/7629_2.png) [@tianrluo](https://discourse.julialang.org/u/tianrluo)\
**Post date:** [August 10, 2019, 4:49am UTC](https://discourse.julialang.org/t/unpacking-cartesianindex/27374/2 "2019-08-10T04:49:01Z")

</div>

Take this:

```julia
for (i, j) in Tuple.(CartesianIndices(a))
  println(i, j)
end

```

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [August 10, 2019, 6:35am UTC](https://discourse.julialang.org/t/unpacking-cartesianindex/27374/4 "2019-08-10T06:35:26Z")

</div>

> [@Charlie\_He](#):
>
> This is an unreasonable design of the Julia interface in my opinion, which implements unpacking using iterator. I suggest Julia have an additional function `unpack` which is called when unpacking syntax is used and only falls back to `iterate` by default

While the wording of this suggestion is rather forceful, there is merit to it, I think.

---

<div class="post-metadata">

**Author:** ![Charlie\_He](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/charlie_he/32/9465_2.png) [@Charlie\_He](https://discourse.julialang.org/u/Charlie_He)\
**Post date:** [August 10, 2019, 6:50am UTC](https://discourse.julialang.org/t/unpacking-cartesianindex/27374/5 "2019-08-10T06:50:28Z")

</div>

It was using `map` to get around this. Thanks

---

<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 11, 2019, 6:07am UTC](https://discourse.julialang.org/t/unpacking-cartesianindex/27374/6 "2019-08-11T06:07:59Z")

</div>

> [@tianrluo](#):
>
> for (i, j) in Tuple.(CartesianIndices(a))  
> println(i, j)  
> end

Note that this (and equivalent `map` version) are allocating because they materialize a vector of tuples.

Compare with a non-allocating alternative (`unpack2` below) which runs about 7x faster on my machine.

```julia
function unpack1(dims)
    s = 0
    for (i, j) in Tuple.(CartesianIndices(dims))
        #println(i, j)
        s += i + j
    end
    return s
end

function unpack2(dims)
    s = 0
    for ci in CartesianIndices(dims)
        i, j = Tuple(ci)
        #println(i, j)
        s += i + j
    end
    return s
end

```

```julia
using BenchmarkTools
const dims = (1000, 1000)
@btime unpack1($dims)
@btime unpack2($dims)

```

Apparently, iteration of a `CartesianIndex` is disabled to avoid a possible performance trap when splatting a `CartesianIndex`. See [#23719](https://github.com/JuliaLang/julia/pull/23719)

If you want to live dangerously, you could define iteration on `CartesianIndex` yourself.  
This version (`unpack3` below) is also non-allocating, and is also ~7x faster than the “materializing” version.

```julia
Base.iterate(ci::CartesianIndex) = iterate(Tuple(ci))
Base.iterate(ci::CartesianIndex, state) = iterate(Tuple(ci), state)

function unpack3(dims)
    s = 0
    for (i, j) in CartesianIndices(dims)
        #println(i, j)
        s += i + j
    end
    return s
end

```

---

<div class="post-metadata">

**Author:** ![under-Peter](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/under-peter/32/3626_2.png) [@under-Peter](https://discourse.julialang.org/u/under-Peter)\
**Post date:** [August 11, 2019, 8:45am UTC](https://discourse.julialang.org/t/unpacking-cartesianindex/27374/7 "2019-08-11T08:45:02Z")

</div>

In this case, a generator expression also works well (although in general generators sometimes are way slower due to type-problems), see:

```julia
julia> function unpack4(dims)
           s = 0
           for (i,j) in (Tuple(c) for c in CartesianIndices(dims))
               s += i + j
           end
           return s
       end

```

which on my system is as fast as `unpack2`.

---

<div class="post-metadata">

**Author:** ![Charlie\_He](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/charlie_he/32/9465_2.png) [@Charlie\_He](https://discourse.julialang.org/u/Charlie_He)\
**Post date:** [August 11, 2019, 8:48am UTC](https://discourse.julialang.org/t/unpacking-cartesianindex/27374/8 "2019-08-11T08:48:01Z")

</div>

I thought `map` returns a generator, which is how python works. It turns out to return a vector.

---

<div class="post-metadata">

**Author:** ![Charlie\_He](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/charlie_he/32/9465_2.png) [@Charlie\_He](https://discourse.julialang.org/u/Charlie_He)\
**Post date:** [August 12, 2019, 9:43am UTC](https://discourse.julialang.org/t/unpacking-cartesianindex/27374/11 "2019-08-12T09:43:30Z")

</div>

Depending on the situation, eager operations is usually more efficient that lazy ones if everything fits into the memory. I’m not sure why in this case it is slower.
