我想创建一个宏来替换多个函数中使用的长表达式,以提高代码的可读性。每个函数对于某个参数具有相同的名称,该参数在宏中使用,但在编译函数时,Julia表示宏中使用的变量即使在转义时也是未定义的。最小的例子:
julia> macro mtest()
esc(x)
end
@mtest (macro with 1 method)
julia> ftest(x) = @mtest
ERROR: UnderVarError: x not defined
现在变得奇怪了:
julia> x = 1
1
julia> @mtest
1
julia> ftest(x) = @mtest
ftest (generic function with 1 method)
julia> ftest(2)
1
为什么此功能定义只是评估为ftest(x) = x
?如何告诉宏使用调用函数范围中的x
而不是REPL?我想使用宏来简单地替换文字的文本块,就像我正在使用的C库中一样:
#define CHECK_STUFF \
big \
complicated \
expression \
involving x;
void func(x, y, z) {
//stuff
CHECK_STUFF
//more stuff
}
在这种情况下,CHECK_STUFF
必须是宏,不是一个函数,因为它包含goto
到func
中的标签}。我的任务是把它翻译成朱莉娅。
答案 0 :(得分:1)
您的宏计算值,而不是表达式。因此,由于宏在编译时而不是在运行时运行,它在编译时基本上会查找esc(x)
,但是,由于x
在编译时为1,因此您的函数将编译为f(x)=1
。你想做的是让你的宏返回表达式x
,这样你的函数就可以编译成f(x)=x
。那就是:
macro mtest()
quote
x
end
end
会奏效。虽然您可以将其设置为:x
,但此语法可以很好地扩展。
事实上,我倾向于在以后引用宏编程"办法。您可以先编写宏并在REPL中测试它,而不返回表达式而是返回值。这就是你在这里所做的。它更容易让它运作起来。但是,为了使它在函数中实际有用,它必须返回一个表达式。所以最简单的方法就是做我刚刚展示的内容:拿走你所拥有的东西并将quote end
放在它周围。现在,如果您有宏的参数,则需要修改表达式,以便正确插值。但是如果通用算法已经有效,那么这部分就不会那么困难了(而且我已经留下了一条面包屑的痕迹,如何在SO上插入很多奇怪的东西,所以如果你想要插入奇怪的东西,只需搜索一下)。