Ray*_*oal 3 macros hygiene julia
我unless在这里找到了Julia中宏的一个例子,如下所示:
macro unless(test, branch)
quote
if !$test
$branch
end
end
end
Run Code Online (Sandbox Code Playgroud)
然而,当我尝试使用它时,它失败了(显然存在卫生问题,但我无法弄明白).这是我使用的测试:
x, y = 0, 1
@unless (x == 5) begin # should execute
y = 3
end
@unless (x == 0) begin # should not execute
y = 5
end
@assert y == 3 # FAILS! SAYS y is 0
Run Code Online (Sandbox Code Playgroud)
现在我可以通过仅转移分支而不是测试来完成这项工作:
macro unless(test, branch)
quote
if !$test
$(esc(branch))
end
end
end
Run Code Online (Sandbox Code Playgroud)
我的问题是:为什么只能逃避分支而不是测试呢?现在我尝试了宏扩展.在第一种情况下,没有esc,我得到这个:
julia> macroexpand(:(@unless (x == 5) begin y = 3 end))
quote # none, line 3:
if !(x == 5) # none, line 4:
begin # none, line 1:
#2#y = 3
end
end
end
Run Code Online (Sandbox Code Playgroud)
现在即使两个宏参数都没有被转义,只有y被诅咒了!任何人都可以解释为什么会这样吗?(我知道第二个版本是有效的,因为当我逃离分支时,y没有被人工化,并且宏扩展到y = 3了预期.但是我完全x不知道为什么即使没有,也没有被人工化使用esc.)
请参阅Julia doc:
宏结果中的变量被分类为本地或全局变量.如果将变量分配给(并且未声明为全局变量),声明为本地变量或将其用作函数参数名称,则该变量被视为本地变量.否则,它被视为全球......
因此,在这种情况下,test部分不会分配任何内容,因此它的变量被视为全局变量,但在branch某种程度上,已y分配,因此它被认为是本地的,并且为其分配新值不会y在模块范围中发生变化.