Tuple Restructuring Syntax

Can someone help me understand why the latter works but the former does not?

map((x, y) -> x * y, zip(xs, ys)) # MethodError
map(((x, y),) -> x * y, zip(xs, ys)) # works

To me the first is akin to the form I usually use:

map(zip(xs, ys)) do (x, y) 
    x*y
end

No it’s like

julia> map(zip(xs, ys)) do x, y
           x*y
       end
ERROR: MethodError: no method matching (::var"#15#16")(::Tuple{Int64, Int64})
1 Like

julia> map(splat((x, y) -> x * y), zip(xs, ys)) #works

or just

julia> map(*, xs, ys)
2 Likes

With the first definition, the function takes two arguments. Trying to pass a single tuple to it will not work.

julia> L = (x, y) -> x * y
#5 (generic function with 1 method)

julia> methods(L)
# 1 method for anonymous function "#5":
 [1] (::var"#5#6")(x, y)
     @ REPL[26]:1

julia> L(1,2)
2

julia> L((1,2))
ERROR: MethodError: no method matching (::var"#5#6")(::Tuple{Int64, Int64})

The second method takes a single argument, a tuple of two values.

julia> M = ((x, y),) -> x * y
#9 (generic function with 1 method)

julia> methods(M)
# 1 method for anonymous function "#9":
 [1] (::var"#9#10")(::Any)
     @ REPL[31]:1

julia> M(1,2)
ERROR: MethodError: no method matching (::var"#9#10")(::Int64, ::Int64)

julia> M((1,2))
2

The MethodError has nothing to do with destructuring syntax. It’s just about the arguments taken, 1 or 2.

Thanks all so far. Why doesn’t the do syntax require the nested tuple definition? E.g. this errors:

map(zip(xs, ys)) do ((x, y),)
           x*y
end

With my current understanding, it seems there’s an inconsistency between the do syntax and anonymous function syntax.

IMO do x, y vs function f((x,y),) is a little inconsistent, yeah.

I might write it as

map(xs, ys) do x, y
   x * y
end

just so I can skip zip()

1 Like