Macros 为什么这个Julia宏不需要“esc”?

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

我在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   # 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
被划分为局部。球状体通过时没有被一元化。当地人被解雇了。逃逸既可以防止生成符号,但对于全局符号则是不必要的。有道理,但不太明显。:)