为什么这个 Julia 宏_不_需要 `esc`?
Why does this Julia macro _not_ require `esc`?
我在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
没有 gensymed 即使没有使用 esc
。)
参考 Julia 文档:
Variables within a macro result are classified as either local or
global. A variable is considered local if it is assigned to (and not
declared global), declared local, or used as a function argument name.
Otherwise, it is considered global....
所以在这种情况下 test
部分没有分配任何东西因此它的变量被认为是全局的,但在 branch
部分,y
被分配因此它被认为是局部的并分配新值它不改变模块范围内的 y
。
我在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
没有 gensymed 即使没有使用 esc
。)
参考 Julia 文档:
Variables within a macro result are classified as either local or global. A variable is considered local if it is assigned to (and not declared global), declared local, or used as a function argument name. Otherwise, it is considered global....
所以在这种情况下 test
部分没有分配任何东西因此它的变量被认为是全局的,但在 branch
部分,y
被分配因此它被认为是局部的并分配新值它不改变模块范围内的 y
。