【问题标题】:Interpolating an Expression into an Expression将表达式内插到表达式中
【发布时间】:2017-02-05 19:48:43
【问题描述】:

我想在宏内部构建一个带有关键字参数的构造函数,并且第一个关键字参数需要用于表达式。我无法将该表达式放入表达式中。这就是我的意思。说我有一个类型

type Test
  ex
end

包含一个表达式。我想创建一个构造函数,其中 origex = :(a * b) 是关键字参数的默认值。我试过了

@eval :(Test(ex=$origex) = Test(origex))

但是如果你看一下下面的表达式:

Test(ex=a * b) = begin  # console, line 1:
    Test(origex)
end

您会发现它不起作用,因为a*b 仍然需要是一个表达式。所以我尝试了

@eval :(Test(ex=:($origex)) = Test(origex))

但这有奇怪的表达

Test(ex=$(Expr(:quote, :($(Expr(:$, :origex)))))) = begin  # console, line 1:
    Test(origex)
end

这也不会eval。相反,我需要得到

Test(ex=:(a * b)) = begin  # console, line 1:
    Test(origex)
end

作为 eval 的表达式,但我不知道如何将该表达式转换为表达式。

【问题讨论】:

    标签: metaprogramming julia


    【解决方案1】:

    我认为以下是您想要的。您似乎犯了一些错误:

    julia> type Test
             ex::Expr
           end
    
    julia> orig_ex = :(a + b)
    :(a + b)
    
    julia> new_ex = Meta.quot(orig_ex)
    :($(Expr(:quote, :(a + b))))
    
    julia> code = :( Test(; ex=$new_ex) = Test(ex) )
    :(Test(; ex=$(Expr(:quote, :(a + b)))) = begin  # REPL[4], line 1:
                Test(ex)
            end)
    
    julia> eval(code)
    Test
    
    julia> Test()
    Test(:(a + b))
    

    【讨论】:

    • 谢谢。那效果很好。 Meta.quot 到底是什么,为什么它与 :(orig_ex) 不同?
    • @ChrisRackauckas Meta.quot(ex) 就是 Expr(:quote, ex): julia> ex = :(a + b); @assert Meta.quot(ex) == Expr(:quote, ex)
    • Meta.quot 增加了另一个级别的引用。如您所见,当您进行插值时,仅使用 :(orig_ex) 不足以保持引用。根据我的经验,这些事情很难做到正确!
    猜你喜欢
    • 2017-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多