消除 Julia 元编程中各种引用机制的歧义
Disambiguate the various quoting mechanisms in Julia metaprogramming
有人可以清楚地列出 Julia 中可用于元编程的各种引用机制,并用一个最小的例子来说明每一种机制吗?
以便清楚在什么情况下使用哪个...
据我所知有:
:(someExpr; maybeMore)
quote; ...expressions... end;
与上面的几乎相同,只是带有用于调试目的的行号
Expr(:quote, x)
其中 (according to @totalverb) 等价于 Meta.quot(x)
- QuoteNode 其中 (according to Jeff Bezanson) "is only used in the internal AST representation, not by macros. It's safe to ignore unless you work on later stages of the compiler."
这个列表全面吗?我是否遗漏了任何替代表示?
:...
是默认的引用机制。它解析一个表达式和 returns AST。
:x == Symbol("x")
:(x + y) == Expr(:call, :+, :x, :y)
:(x; y; z) == Expr(:block, :x, :y, :z)
eval(:<expr>)
应该 return 与 <expr>
相同(假设 <expr>
是当前全局 space 中的有效表达式)
eval(:(1 + 2)) == 1 + 2
eval(:(let x=1; x + 1 end)) == let x=1; x + 1 end
quote ... end
等同于 :(begin ... end)
Expr(:quote, x)
用于表示引号中的引号。
Expr(:quote, :(x + y)) == :(:(x + y))
Expr(:quote, Expr(:$, :x)) == :(:($x))
QuoteNode(x)
类似于 Expr(:quote, x)
但它防止插值。
eval(Expr(:quote, Expr(:$, 1))) == 1
eval(QuoteNode(Expr(:$, 1))) == Expr(:$, 1)
这是一个使用了所有这些的宏:
macro quoted(expression)
quote
println("received expression: :(", $(QuoteNode(expression)), ")")
$(Expr(:quote, expression))
end
end
用法:
julia> x = 1
1
julia> @quoted $x + 1
received expression: :($(Expr(:$, :x)) + 1)
:(1 + 1)
julia> @quoted :(x + 1)
received expression: :($(Expr(:quote, :(x + 1))))
:($(Expr(:quote, :(x + 1))))
编辑:Meta.quot(x)
确实和Expr(:quote, x)
一样。它没有记录,也没有在任何地方提到,但它是对 Base
(https://github.com/JuliaLang/julia/pull/1755) 导出的函数的有意识的补充,我还没有看到任何弃用它的计划,所以你可以使用它。
有人可以清楚地列出 Julia 中可用于元编程的各种引用机制,并用一个最小的例子来说明每一种机制吗?
以便清楚在什么情况下使用哪个...
据我所知有:
:(someExpr; maybeMore)
quote; ...expressions... end;
与上面的几乎相同,只是带有用于调试目的的行号Expr(:quote, x)
其中 (according to @totalverb) 等价于Meta.quot(x)
- QuoteNode 其中 (according to Jeff Bezanson) "is only used in the internal AST representation, not by macros. It's safe to ignore unless you work on later stages of the compiler."
这个列表全面吗?我是否遗漏了任何替代表示?
:...
是默认的引用机制。它解析一个表达式和 returns AST。
:x == Symbol("x")
:(x + y) == Expr(:call, :+, :x, :y)
:(x; y; z) == Expr(:block, :x, :y, :z)
eval(:<expr>)
应该 return 与 <expr>
相同(假设 <expr>
是当前全局 space 中的有效表达式)
eval(:(1 + 2)) == 1 + 2
eval(:(let x=1; x + 1 end)) == let x=1; x + 1 end
quote ... end
等同于 :(begin ... end)
Expr(:quote, x)
用于表示引号中的引号。
Expr(:quote, :(x + y)) == :(:(x + y))
Expr(:quote, Expr(:$, :x)) == :(:($x))
QuoteNode(x)
类似于 Expr(:quote, x)
但它防止插值。
eval(Expr(:quote, Expr(:$, 1))) == 1
eval(QuoteNode(Expr(:$, 1))) == Expr(:$, 1)
这是一个使用了所有这些的宏:
macro quoted(expression)
quote
println("received expression: :(", $(QuoteNode(expression)), ")")
$(Expr(:quote, expression))
end
end
用法:
julia> x = 1
1
julia> @quoted $x + 1
received expression: :($(Expr(:$, :x)) + 1)
:(1 + 1)
julia> @quoted :(x + 1)
received expression: :($(Expr(:quote, :(x + 1))))
:($(Expr(:quote, :(x + 1))))
编辑:Meta.quot(x)
确实和Expr(:quote, x)
一样。它没有记录,也没有在任何地方提到,但它是对 Base
(https://github.com/JuliaLang/julia/pull/1755) 导出的函数的有意识的补充,我还没有看到任何弃用它的计划,所以你可以使用它。