Macros 为什么这个Julia宏不需要“esc”?
我在Julia中找到了一个Macros 为什么这个Julia宏不需要“esc”?,macros,julia,hygiene,Macros,Julia,Hygiene,我在Julia中找到了一个除非宏的示例,编写如下: macro unless(test, branch) quote if !$test $branch end end end 然而,当我尝试使用它时,它失败了(显然有卫生问题,但我不能准确地找出它)。以下是我使用的测试: x, y = 0, 1 @unless (x == 5) begin # should execute y = 3 end @unless (x == 0) begin # s
除非宏的示例,编写如下:
macro unless(test, branch)
quote
if !$test
$branch
end
end
end
然而,当我尝试使用它时,它失败了(显然有卫生问题,但我不能准确地找出它)。以下是我使用的测试:
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
现在,我可以通过仅转义分支而不是测试来实现这一点:
macro unless(test, branch)
quote
if !$test
$(esc(branch))
end
end
end
我的问题是:为什么只逃避分支而不逃避测试就足够了?现在我确实尝试了宏扩展。在第一种情况下,如果没有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
现在,即使两个宏参数都没有转义,只有y
被gensymed!有人能解释为什么会这样吗?(我知道第二个版本是有效的,因为当我退出分支时,y没有得到gensymed,宏按预期扩展到y=3
。但是我完全不知道为什么x
没有gensymed,即使没有使用esc
)参考Julia doc:
宏结果中的变量分为局部变量和局部变量
全球的。如果变量被分配给(而不是
声明全局)、声明局部或用作函数参数名。
否则,它被认为是全球性的
因此,在这种情况下,test
部件不分配任何变量,因此它的变量被视为全局变量,但在分支
部件中,y
被分配,因此它被视为局部变量,并且为其分配新值不会改变模块范围中的y
好的,我明白了,x
被划分为全局,而y
被划分为局部。球状体通过时没有被一元化。当地人被解雇了。逃逸既可以防止生成符号,但对于全局符号则是不必要的。有道理,但不太明显。:)