将字符串插值传递给宏

播客

我的这段代码的问题是,在传递插值字符串时,宏会失败:

macro t(a, b, c)
    quote
        println(:c, " = " , $c)
        ($a, $b, $c)
    end
end

function test()
    # works:
    @t 1 2 3

    # doesn't work:
    x = π
    @t 1 2 "x is $x"
end

test()
test()
c = 3   # works
ERROR: UndefVarError: x not defined

因此,内t插值x不可用。有解决方案吗,还是在这里使用宏只是一个坏主意?

BogumiłKamiński

为了实现您想要的,您需要使用esc

macro t(a, b, c)
    quote
        local a1 = $(esc(a))
        local b1 = $(esc(b))
        local c1 = $(esc(c))
        println(:c, " = ", c1)
        (a1, b1, c1)
    end
end

请注意,我定义的变量a1b1以及c1一次,然后再使用它们。原因是,如果您编写了以下内容:

macro t(a, b, c)
    quote
        println(:c, " = ", $(esc(c)))
        ($(esc(a)), $(esc(b)), $(esc(c)))
    end
end

这是很自然的事情(或者可能不是:)),您将遇到问题c,例如两次评估。在此示例中:

julia> macro t(a, b, c)
           quote
               println(:c, " = ", $(esc(c)))
               ($(esc(a)), $(esc(b)), $(esc(c)))
           end
       end
@t (macro with 1 method)

julia> function test()
           @t 1 2 rand()
       end
test (generic function with 1 method)

julia> test()
c = 0.03771143425073453
(1, 2, 0.1819496773810383)

请注意,将打印一个不同的值并返回不同的值。此问题存在于您的原始宏中(即使它使用了@Bill指出的全局变量):

julia> macro t(a, b, c)
           quote
               println(:c, " = " , $c)
               ($a, $b, $c)
           end
       end
@t (macro with 1 method)

julia> @t 1 2 rand()
c = 0.7021554643798531
(1, 2, 0.6363717837673994)

总的来说,当您使用元编程调试代码时,我认为@code_lowered@macroexpand宏对您将很有用。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章