为什么这样做:
function test_func(a, b)
a + b
end
test_func((1, 2)...)
但这不是吗?
macro test_func(a, b)
a + b
end
@test_func((1, 2)...)
这是朱莉娅的错误吗?
答案 0 :(得分:12)
宏对表面语法进行操作,因此@test_func
没有看到splat的结果。相反,它看到了splat操作本身!与往常一样,检查它的一个好方法是引用它并查看宏正在运行的语法:
julia> :(@test_func((1,2)...))
:(@test_func (1,2)...)
julia> Meta.show_sexpr(ans)
(:macrocall, symbol("@test_func"), (:..., (:tuple, 1, 2)))
因此宏只接收一个参数(而不是两个),它是一个Expr(:..., Expr(:tuple, 1, 2))
。请注意,元组(1,2)是传递给您的宏,但它只是隐藏在splat操作中。所以你可以深入研究Expr
和各种各样的工具:
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
但这只是一种支持splatting的类型。看看如果你尝试操作一个变量会发生什么:
julia> @test_func(xs...)
ERROR: unsupported syntax (:(xs...),)
现在没有办法让宏知道它应该加在一起了什么!