Bug with `@.`

I think I’ve found a bug with the @. macro

julia> function foo(;x = 0, y = 8)
       return x
       end
foo (generic function with 1 method)

julia> a = [1, 2, 3]; b = [4, 5, 6];

julia> foo(; x = @. a * b, y = b)
ERROR: DimensionMismatch("array could not be broadcast to match destination")

I think @. is being too “greedy”, for lack of a better word. It’s not respecting the fact that it’s scope ends at the ,. For instance

julia> foo(; x = @. a * b,)
ERROR: syntax: unexpected ")"

But

julia> foo(;x = @. a & b)
3-element Array{Int64,1}:
 0
 0
 2

Sorry for focusing on keyword arguments, here is another example with positional arguments.

julia> bar(x, y) = x 
bar (generic function with 1 method)

julia> bar(@. a * b, b)
ERROR: MethodError: no method matching bar(::Tuple{Array{Int64,1},Array{Int64,1}})

Without parentheses, the parser will give all arguments to the macro. This is not specific to the @. macro. Try, for example, bar(@show a + b, b); It will give the same error.

To delimit what goes to the macro, use either a newline:

 bar(@. a * b
     , b)

or parentheses

bar(@.(a * b), b)
1 Like

You need @.(a * b) or (@. a * b).

This is not a bug, and is not specific to @. — any macro takes as much of the next expression as possible. That is, @. a * b, y = b is equivalent to @. (a * b, y = b) — it is parsing the next two arguments as a tuple.

1 Like

Indeed

julia> macro t(x)
       @show x
       x
       end
@t (macro with 1 method)

julia> bar(@t a, b)
x = :((a, b))

Thanks. I guess this allows stuff like

@unpack a, b = x

to work.

Note that you can also do

bar(begin @. a * b end, b)

which might be more intuitive for a complicated expression.