Julia - 在函数中使用但不在REPL

时间:2016-11-17 18:09:14

标签: macros julia

我想创建一个宏来替换多个函数中使用的长表达式,以提高代码的可读性。每个函数对于某个参数具有相同的名称,该参数在宏中使用,但在编译函数时,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 必须是宏,不是一个函数,因为它包含gotofunc中的标签}。我的任务是把它翻译成朱莉娅。

1 个答案:

答案 0 :(得分:1)

您的宏计算值,而不是表达式。因此,由于宏在编译时而不是在运行时运行,它在编译时基本上会查找esc(x),但是,由于x在编译时为1,因此您的函数将编译为f(x)=1 。你想做的是让你的宏返回表达式x,这样你的函数就可以编译成f(x)=x。那就是:

macro mtest()
    quote 
       x
    end
end

会奏效。虽然您可以将其设置为:x,但此语法可以很好地扩展。

事实上,我倾向于在以后引用宏编程"办法。您可以先编写宏并在REPL中测试它,而不返回表达式而是返回值。这就是你在这里所做的。它更容易让它运作起来。但是,为了使它在函数中实际有用,它必须返回一个表达式。所以最简单的方法就是做我刚刚展示的内容:拿走你所拥有的东西并将quote end放在它周围。现在,如果您有宏的参数,则需要修改表达式,以便正确插值。但是如果通用算法已经有效,那么这部分就不会那么困难了(而且我已经留下了一条面包屑的痕迹,如何在SO上插入很多奇怪的东西,所以如果你想要插入奇怪的东西,只需搜索一下)。