Macro & tuple parsing

I expect that this came up before, but I could not find an issue, so I am asking here. Consider

macro greedy(expr)
    esc(expr)
end

f(x, y) = x + y

then

julia> f(1, 2)
3

julia> f(@greedy 1, 2)
ERROR: MethodError: no method matching f(::Tuple{Int64,Int64})
Closest candidates are:
  f(::Any, ::Any) at REPL[34]:1

The issue is that

julia> parse("f(@greedy x, y)")
:(f(@greedy((x, y))))

so the macro takes the whole tuple as its argument.

This is a corner case of the use of , for function arguments and tuple element separators. I can see some logic behind it, and know that f(@greedy(1), 2) is a workaround, but parsing "f(@greedy x, y)" as :(f(@greedy(x), y)) would occasionally feel more natural.

Imagine an expression like @inbounds x, y = a[1]: you really want @inbounds to apply to the whole destructured-tuple assignment, not just to x. That’s why the non-parenthesized form of macro application can’t be “greedy”.

The basic rule of thumb is that you should use @greedy x y ... only when you are applying a macro to a whole line (or a larger block), and use @greedy(x,y) otherwise.

2 Likes

I understand the rationale, but perhaps the documentation could clarify this.

1 Like