Julia 朱莉娅:把字符串传给宏
假设我有一个宏定义为:Julia 朱莉娅:把字符串传给宏,julia,Julia,假设我有一个宏定义为: macro foomacro(ex::Expr) dump(ex) ex end 目前,我希望以解析字符串的形式传递表达式,以便传递通过字符串串联获得的相当复杂且大小写相关的表达式 然而,尝试: @foomacro 1+2+3 给出了预期的结果6 @foomacro parse("1+2+3") 返回解析后的表达式:(1+2+3),而不是实际解析它 据我所知,这两个宏应该接收相同的表达式,但显然不是这样 我如何让这个MWE工作 ps:我想出了这个解决
macro foomacro(ex::Expr)
dump(ex)
ex
end
目前,我希望以解析字符串的形式传递表达式,以便传递通过字符串串联获得的相当复杂且大小写相关的表达式
然而,尝试:
@foomacro 1+2+3
给出了预期的结果6
@foomacro parse("1+2+3")
返回解析后的表达式:(1+2+3),而不是实际解析它
据我所知,这两个宏应该接收相同的表达式,但显然不是这样
我如何让这个MWE工作
ps:我想出了这个解决方案,但我觉得它非常脏而且“不正确”
ps:如果这是相关的,那么目前代码运行在0.6.4上,如果可能的话,我宁愿不更新到1.0,因为这会将我的实际项目推迟到很多…你把级别弄混了。为了清晰起见,让我们引入一个中间函数:
function foomacro_impl(expr)
dump(expr)
expr
end
macro foomacro(expr)
foomacro_impl(expr)
end
如果运行,将解析表达式@foomacro
,将
部分传递到foomacro\u impl
,并将结果视为表达式并插入,而不是原始表达式。这意味着编写@foomacro 1+2+3
相当于编写
let expr = :(1+2+3)
dump(expr)
expr
end
返回
Expr
head: Symbol call
args: Array{Any}((4,))
1: Symbol +
2: Int64 1
3: Int64 2
4: Int64 3
:(1 + 2 + 3)
计算结果为6的Expr
另一方面,在@foomacro Meta.parse(“1+2+3”)
中,整个参数parse(“1+2+3”)
用作expr
:
julia> let expr = :(Meta.parse("1+2+3"))
dump(expr)
expr
end
Expr
head: Symbol call
args: Array{Any}((2,))
1: Expr
head: Symbol .
args: Array{Any}((2,))
1: Symbol Meta
2: QuoteNode
value: Symbol parse
2: String "1+2+3"
:(Meta.parse("1+2+3"))
因此,宏调用的结果是表达式Meta.parse(“1+2+3”)
,它的计算结果是另一个表达式:(1+2+3)
,因为它是对parse
的调用。因此,这两种形式没有得到相同的表达
但是有一些方法可以手动解析表达式并将其传递给宏:
@foomacro bla
返回的表达式等价于foomacro_impl(Meta.parse(bla))
。(顺便说一句,这种方法对于测试非常有用,我大多数时候都推荐它。)@eval
构造表达式,拼接到其中,然后立即对其求值:
julia> @eval @foomacro $(Meta.parse("1+2+3"))
Expr
head: Symbol call
args: Array{Any}((4,))
1: Symbol +
2: Int64 1
3: Int64 2
4: Int64 3
6
(或者类似地,使用eval
和手动构造的Expr
值。)你把层次搞混了。为了清晰起见,让我们引入一个中间函数:
function foomacro_impl(expr)
dump(expr)
expr
end
macro foomacro(expr)
foomacro_impl(expr)
end
如果运行,将解析表达式@foomacro
,将
部分传递到foomacro\u impl
,并将结果视为表达式并插入,而不是原始表达式。这意味着编写@foomacro 1+2+3
相当于编写
let expr = :(1+2+3)
dump(expr)
expr
end
返回
Expr
head: Symbol call
args: Array{Any}((4,))
1: Symbol +
2: Int64 1
3: Int64 2
4: Int64 3
:(1 + 2 + 3)
计算结果为6的Expr
另一方面,在@foomacro Meta.parse(“1+2+3”)
中,整个参数parse(“1+2+3”)
用作expr
:
julia> let expr = :(Meta.parse("1+2+3"))
dump(expr)
expr
end
Expr
head: Symbol call
args: Array{Any}((2,))
1: Expr
head: Symbol .
args: Array{Any}((2,))
1: Symbol Meta
2: QuoteNode
value: Symbol parse
2: String "1+2+3"
:(Meta.parse("1+2+3"))
因此,宏调用的结果是表达式Meta.parse(“1+2+3”)
,它的计算结果是另一个表达式:(1+2+3)
,因为它是对parse
的调用。因此,这两种形式没有得到相同的表达
但是有一些方法可以手动解析表达式并将其传递给宏:
@foomacro bla
返回的表达式等价于foomacro_impl(Meta.parse(bla))
。(顺便说一句,这种方法对于测试非常有用,我大多数时候都推荐它。)@eval
构造表达式,拼接到其中,然后立即对其求值:
julia> @eval @foomacro $(Meta.parse("1+2+3"))
Expr
head: Symbol call
args: Array{Any}((4,))
1: Symbol +
2: Int64 1
3: Int64 2
4: Int64 3
6
(或者类似地,使用eval
和手动构造的Expr
值。)也许你想
eval(解析(“1+2+3”))
?不,我试过了,它在这种情况下有效(因为宏传递6,因此返回6),但它在我的非MWE中不起作用,因为宏实际上是在做事情。也许你想eval(解析(“1+2+3”)
?不,我试过了,它在这种情况下有效(因为宏被传递6,因此返回6)但它在我的非MWE中不起作用,因为宏实际上是执行操作的。非常感谢您的深入回答,但是当我尝试todo=“1+2+3”然后尝试ATeval ATfoomacro$(Meta.parse(todo))时,这两种方法似乎都失败了使用foo_impl
可能需要在它之后额外调用eval
,因为它只返回宏将构造的表达式。另一个变体对我来说很有用。不过,有一件事是,Julia 1.0中需要Meta.parse
,而在旧版本中只是parse
——我不知道这是否可以使用任何问题…事实上,我应该计算结果表达式,但这会返回一个错误,即使foo_impl生成的表达式和宏相同,但宏的计算方式不同,这可能吗?您的解决方案在我的特定情况下无法工作,但这很可能与whic的基础函数有关h我无法提供MWE。但是,答案确实回答了与MWE相关的问题,因此我会接受其他遇到相同问题的人的答案:)嗯。您可以尝试使用调试您的问题,以查看调用结果。非常感谢您的深入回答,但是当我尝试todo=“1+2+3”,然后是ATeval ATfoomacro$(Meta.parse(todo))使用foo_impl
可能需要在它之后额外调用eval
,因为它只返回宏将构造的表达式。另一个变体对我来说很有用。不过,有一件事是,Julia 1.0中需要Meta.parse
,而在旧版本中只是parse
——我不知道这是否可以使用任何问题…事实上,我应该计算结果表达式,但这会返回一个错误,即使foo_impl生成的表达式和宏在某种程度上是相同的