模块中Julia宏中表达式和变量的范围

scope of expressions and variables in Julia macro in modules

由于某些原因,我不得不在宏中放入quote ... end块,并以编程方式生成ex。 此代码有效。

1
2
3
4
5
6
7
8
9
10
11
macro addsum_out()
  quote
    ex = :(x+y)
    sum(eval(ex))
  end
end

x = [1 1 1]
y = [2 2 2]

z2 = @addsum_out

将宏放入模块后,它将不再起作用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module MyModule

export @addsum

macro addsum()
  quote
    ex = :(x+y)
    sum(eval(ex))
  end
end

end

using MyModule
x = [1 1 1]
y = [2 2 2]    
z = @addsum

它说:

1
ERROR: LoadError: UndefVarError: x not defined

我认为我应该将esc放在某个地方,以在模块外部的主作用域中评估表达式ex。 我该怎么办?


这里的问题是,引用x的宏(在模块内部)将在该模块中查找x,例如 MyModule.x

这是宏观卫生的一部分。

为防止发生宏卫生问题,您需要esc(x) -这意味着它将使用呼叫现场范围内的x。

您的完整解决方案可能如下所示:

1
2
3
4
5
macro addsum_out()
  quote
    esc(x) + esc(y)
  end
end

或更简而言之:

1
2
3
macro addsum_out()
  :(  esc(x) + esc(y)  )
end

请注意,这与esc( :(x+y) )略有不同,后者也是对+函数的转义。 即包含此宏的模块可能包含+的重载,如果要使用此重载,请不要转义+,否则请执行!

我整理的指南中对此主题进行了一些讨论:
https://github.com/p-i-/MetaGuideJulia/wiki#example-swap-macro-to-illustrate-esc