【问题标题】:Why does this Julia macro _not_ require `esc`?为什么这个 Julia 宏_not_需要`esc`?
【发布时间】:2015-10-20 04:57:51
【问题描述】:

我在 Julia here 中找到了一个 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 被生成了!谁能解释为什么会这样? (我知道第二个版本有效,因为当我逃离分支时, y 没有得到 gensymed 并且宏按预期扩展为 y = 3。但我完全不知道为什么 x 不是即使没有使用 esc,也可以生成 gensymed。)

【问题讨论】:

    标签: macros julia hygiene


    【解决方案1】:

    参考 Julia 文档:

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

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

    【讨论】:

    • 好的,我明白了,所以x 被归类为全局,y 被归类为本地。全局变量在没有被 gensymed 的情况下通过。当地人得到 gensymed。转义要么防止生成对称,但对于全局变量是不必要的。有道理,但不是很明显。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    • 2013-11-09
    相关资源
    最近更新 更多