Why does this work:
function test_func(a, b)
a + b
end
test_func((1, 2)...)
But this does not?
macro test_func(a, b)
a + b
end
@test_func((1, 2)...)
Is it a bug in Julia?
Macros operate on surface syntax, so @test_func
isn't seeing the result of the splat. Instead, it sees the splat operation itself! As always, a great way to inspect this is to quote it and see exactly what syntax the macro is operating on:
julia> :(@test_func((1,2)...))
:(@test_func (1,2)...)
julia> Meta.show_sexpr(ans)
(:macrocall, symbol("@test_func"), (:..., (:tuple, 1, 2)))
So the macro is only receiving one argument (not two), and it's an Expr(:..., Expr(:tuple, 1, 2))
. Notice that the tuple (1,2) is getting passed to your macro, but it's just hidden away inside the splat operation. So you could dig into the Expr
and kind-of-sort-of implement splatting yourself:
julia> macro test_func(as...)
if length(as) == 1 && isa(as[1], Expr) && as[1].head == :... &&
isa(as[1].args[1], Expr) && as[1].args[1].head == :tuple
a, b = as[1].args[1].args
elseif length(as) == 2
a, b = as
else
error("unsupported syntax $as")
end
return esc(:($a + $b))
end
julia> @test_func((1,2)...)
3
But this only kind-of-sort-of supports splatting. Look what happens if you try to operate on a variable instead:
julia> @test_func(xs...)
ERROR: unsupported syntax (:(xs...),)
There's now no way for the macro to know what it should be adding together!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With