Julia宏展开

9

为什么这个有效:

function test_func(a, b)
  a + b
end

test_func((1, 2)...)

但这并不是这样吗?
macro test_func(a, b)
  a + b
end

@test_func((1, 2)...)

这是Julia的一个bug吗?

1个回答

12
宏操作作用于表面语法,所以@test_func没有看到splat的结果。相反,它看到了splat操作本身!像往常一样,检查这个的好方法是引用它并查看宏正在操作的确切语法:

宏操作作用于表面语法,因此@test_func没有看到展开的结果。 相反,它看到的是展开操作本身! 像往常一样,检查这个的好方法是引用它并查看宏正在操作的确切语法:

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并实现类似splat的功能:
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

但是这只是有点支持展开。看看如果你尝试对一个变量进行操作会发生什么:

julia> @test_func(xs...)
ERROR: unsupported syntax (:(xs...),)

现在宏无法知道它应该添加什么!


现在宏无法知道应该添加什么!那句话真的帮了我很多。谢谢。 - Julia Learner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接