4

我在 Julia 中找到了一个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

现在,即使没有一个宏参数被转义,只有ygensymed !谁能解释为什么会这样?(我知道第二个版本有效,因为当我逃离分支时, y 没有得到 gensymed 并且宏y = 3按预期扩展。但我完全不知道为什么x即使没有 gensymed 也没有使用esc。)

4

1 回答 1

5

请参阅 Julia 文档:

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

所以在这种情况下,test部分没有分配任何东西,因此它的变量被认为是全局的,但branch部分y是被分配的,因此它被认为是本地的,并且为它分配新值不会y在模块范围内改变。

于 2015-10-20T08:20:16.747 回答