"do" notation over tuples

What am I doing wrong here?

``````julia> inds = [(i,j) for i in 1:3, j in 1:5]
3×5 Array{Tuple{Int64,Int64},2}:
(1, 1)  (1, 2)  (1, 3)  (1, 4)  (1, 5)
(2, 1)  (2, 2)  (2, 3)  (2, 4)  (2, 5)
(3, 1)  (3, 2)  (3, 3)  (3, 4)  (3, 5)

julia> map(((i,j),) -> i+j, inds)
3×5 Array{Int64,2}:
2  3  4  5  6
3  4  5  6  7
4  5  6  7  8

julia> map(inds) do ((i,j),) i+j end
ERROR: BoundsError: attempt to access 1
at index [2]
Stacktrace:
[1] indexed_iterate(::Int64, ::Int64, ::Nothing) at ./tuple.jl:69
[2] (::getfield(Main, Symbol("##94#95")))(::Tuple{Int64,Int64}) at ./REPL[66]:1
[3] iterate at ./generator.jl:47 [inlined]
[4] _collect at ./array.jl:632 [inlined]
[5] collect_similar(::Array{Tuple{Int64,Int64},2}, ::Base.Generator{Array{Tuple{Int64,Int64},2},getfield(Main, Symbol("##94#95"))}) at ./array.jl:561
[6] map(::Function, ::Array{Tuple{Int64,Int64},2}) at ./abstractarray.jl:1995
[7] top-level scope at none:0
``````
``````julia> map(inds) do (i,j) i+j end
3×5 Array{Int64,2}:
2  3  4  5  6
3  4  5  6  7
4  5  6  7  8
``````

The syntax for `do` notation is a little confusing — it takes arguments as `x, y, z` and not `(x, y, z)`. It’s clearer if we look at this on multiple lines:

``````map(inds) do i, j
i+j
end
``````

The version above takes two arguments called `i` and `j`;

``````map(inds) do (i, j)
i+j
end
``````

This one destructures a single argument into a tuple.

3 Likes

Oh weird, could have sworn I’d already tried that. Thank you!

1 Like

Why not just sum?

``````julia> inds = [(i,j) for i in 1:3, j in 1:5]
3×5 Array{Tuple{Int64,Int64},2}:
(1, 1)  (1, 2)  (1, 3)  (1, 4)  (1, 5)
(2, 1)  (2, 2)  (2, 3)  (2, 4)  (2, 5)
(3, 1)  (3, 2)  (3, 3)  (3, 4)  (3, 5)

julia> sum.(inds)
3×5 Array{Int64,2}:
2  3  4  5  6
3  4  5  6  7
4  5  6  7  8
``````

What I posted isn’t the real problem. For a DSL I made a `For` that works like `map`, so I can write things like

``````For(inds) do (i,j)
f(i,j)
end
``````

Aha, OK I didn’t imagine that, so @yurivish reply is good enough for this.

1 Like