为什么这个Julia宏_not_需要`esc`?

时间:2015-10-20 04:57:51

标签: macros julia hygiene

我在Julia here中找到了一个 { "PHP_EXTENSIONS": ["mysqli"] } 宏的示例,其编写如下:

unless

然而,当我尝试使用它时,它失败了(显然存在卫生问题,但我无法弄明白)。这是我使用的测试:

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。但我完全不知道为什么{{1即使没有使用y = 3,也没有被诅咒。)

1 个答案:

答案 0 :(得分:5)

请参阅Julia doc:

  

宏结果中的变量被分类为local或   全球。如果将变量分配给(而不是变量),则该变量被视为本地变量   声明全局),声明为local,或用作函数参数名称。   否则,它被视为全球......

因此,在这种情况下,test部分不会分配任何内容,因此它的变量被视为全局变量,但在branch部分中,y已分配,因此它被视为本地并为其分配新值不要更改模块范围中的y