2015-10-20 83 views
3

我发现一个unless宏的例子在写朱莉娅here如下:这个Julia宏为什么不需要`esc`?

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

回答

5

参考朱莉娅DOC:宏结果中

变量分为本地或全局 。如果一个变量被分配给(而不是全局声明的),声明为本地的,或者被用作函数参数名称,则该变量被认为是本地的。 否则,它被认为是全球....

因此,在这种情况下test部分不指定任何东西,因此它被认为是全局变量,但在branch部分,y我被分配因此它被视为本地和分配新的价值它不会在模块范围内更改y

+1

好的,我明白了,所以'x'被分类为全局和'y'作为本地。全局通过而不会被gensymed。当地人得到gensymed。转义可以防止gensymming,但对全局变量不是必需的。有道理,但不是很明显。 :) –

相关问题