# How to CartesianIndex array comprehension?

Hey community

``````julia> CartesianIndex(1,1) .+ [CartesianIndex(i,i) for i in 1:10]
ERROR: iteration is deliberately unsupported for CartesianIndex. Use `I` rather than `I...`, or use `Tuple(I)...`
Stacktrace:
[1] error(::String) at .\error.jl:33
[2] iterate(::CartesianIndex{2}) at .\multidimensional.jl:164
[3] copyto!(::Array{Int64,1}, ::CartesianIndex{2}) at .\abstractarray.jl:721
[4] _collect(::UnitRange{Int64}, ::CartesianIndex{2}, ::Base.HasEltype, ::Base.HasLength) at .\array.jl:609
[5] collect(::CartesianIndex{2}) at .\array.jl:603
[8] top-level scope at REPL[5]:1
``````

`(CartesianIndex(1,1),) .+ [CartesianIndex(i,i) for i in 1:10]`

Wrapping it in a tuple indicates the first argument is to be broadcast. This is arguably a case where defensive programming gets in the way. If we were confident that no one would try to broadcast over the āelementsā of a `CartesianIndex` we could make what you tried work.

3 Likes

Why not replace it with:

``````[CartesianIndex(1,1) + CartesianIndex(i,i) for i in 1:10]
``````

E.g.,

``````julia> v = reshape(1:121,11,11)
11Ć11 reshape(::UnitRange{Int64}, 11, 11) with eltype Int64:
1  12  23  34  45  56  67  78  89  100  111
2  13  24  35  46  57  68  79  90  101  112
3  14  25  36  47  58  69  80  91  102  113
4  15  26  37  48  59  70  81  92  103  114
5  16  27  38  49  60  71  82  93  104  115
6  17  28  39  50  61  72  83  94  105  116
7  18  29  40  51  62  73  84  95  106  117
8  19  30  41  52  63  74  85  96  107  118
9  20  31  42  53  64  75  86  97  108  119
10  21  32  43  54  65  76  87  98  109  120
11  22  33  44  55  66  77  88  99  110  121

julia> v[[CartesianIndex(1,1)+CartesianIndex(i,i) for i in 1:10]]
10-element Array{Int64,1}:
13
25
37
49
61
73
85
97
109
121
``````

ā¦if that is what you want.

Oh I understand. Itās not clear what to doā¦

``````julia> [each for each in CartesianIndex(1,1)]
ERROR: iteration is deliberately unsupported for CartesianIndex. Use `I` rather than `I...`, or use `Tuple(I)...`
Stacktrace:
[1] error(::String) at .\error.jl:33
[2] iterate(::CartesianIndex{2}) at .\multidimensional.jl:164
[3] iterate at .\generator.jl:44 [inlined]
[4] collect(::Base.Generator{CartesianIndex{2},typeof(identity)}) at .\array.jl:665
[5] top-level scope at REPL[13]:1

julia> iterate(CartesianIndex(1,1))
ERROR: iteration is deliberately unsupported for CartesianIndex. Use `I` rather than `I...`, or use `Tuple(I)...`
Stacktrace:
[1] error(::String) at .\error.jl:33
[2] iterate(::CartesianIndex{2}) at .\multidimensional.jl:164
[3] top-level scope at REPL[14]:1

julia> for each in CartesianIndex(1,1) println(each) end
ERROR: iteration is deliberately unsupported for CartesianIndex. Use `I` rather than `I...`, or use `Tuple(I)...`
Stacktrace:
[1] error(::String) at .\error.jl:33
[2] iterate(::CartesianIndex{2}) at .\multidimensional.jl:164
[3] top-level scope at .\REPL[15]:1
``````

Right. The bottom line is we want people to use `CartesianIndex` like a scalar; `A[3, 4]` should be identical in every respect with `A[CartesianIndex(3, 4)]`. That imposes certain rules with respect to broadcasting, including the fact that you canāt iterate over `(3, 4)` as if itās a list. But what we donāt (yet) do is trust that people wonāt try to iterate over those entries, so we look for that and try to throw a helpful error. However, in your case, that attempt to be helpful actually got in the way of the perfectly well-justified idea you had in the beginning.

4 Likes