是否有内置的Julia函数用于剥离LineNumberNode
中的Expr
?尤其是对于宏调用:
julia> ex = :(@foo 1)
:(#= REPL[5]:1 =# @foo 1)
julia> dump(ex)
Expr
head: Symbol macrocall
args: Array{Any}((3,))
1: Symbol @foo
2: LineNumberNode
line: Int64 1
file: Symbol REPL[5]
3: Int64 1
尝试过MacroTools.striplines
,但是
julia> ex = :(@foo 1+1)
:(#= REPL[7]:1 =# @foo 1 + 1)
julia> MacroTools.striplines(ex) |> dump
Expr
head: Symbol macrocall
args: Array{Any}((3,))
1: Symbol @foo
2: LineNumberNode
line: Int64 1
file: Symbol REPL[7]
3: Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol +
2: Int64 1
3: Int64 1
我的用例是比较构造在不同文件中的两个不同的expr(因此,不同的行号信息)。我当前的解决方法是显式编写Expr(:macrocall,Symbol(“ @ foo”),什么都没有,:(1 + 1)),这有点冗长。
答案 0 :(得分:3)
不是内置的,但是MacroTools.jl具有MacroTools.striplines(ex)
,可从表达式中删除LineNumberNodes
。
答案 1 :(得分:3)
内置函数为Base.remove_linenums!
:
julia> ex = quote begin
x = 3
y = 2
z = 4
foo(x) = 3
end
end
quote
#= REPL[2]:1 =#
begin
#= REPL[2]:2 =#
x = 3
#= REPL[2]:3 =#
y = 2
#= REPL[2]:4 =#
z = 4
#= REPL[2]:5 =#
foo(x) = begin
#= REPL[2]:5 =#
3
end
end
end
julia> Base.remove_linenums!(ex)
quote
begin
x = 3
y = 2
z = 4
foo(x) = begin
3
end
end
end
亚历克斯·阿尔斯兰(Alex Arslan)提醒我。
答案 2 :(得分:2)
由于您的目标是能够比较Expr
,因此可以将LineNumberNode
替换为nothing
。这样可以进行比较,并且Expr
仍然有效。请参见下面的示例:
julia> macro hello(world)
println("hello ",world)
end
@hello (macro with 1 method)
julia> m1 = :(@hello "world")
:(#= REPL[99]:1 =# @hello "world")
julia> m2 = :(@hello "world")
:(#= REPL[100]:1 =# @hello "world")
julia> m1 == m2
false
julia> replace!(arg -> typeof(arg) <: LineNumberNode ? nothing : arg, m1.args);
julia> replace!(arg -> typeof(arg) <: LineNumberNode ? nothing : arg, m2.args);
julia> dump(m1)
Expr
head: Symbol macrocall
args: Array{Any}((3,))
1: Symbol @hello
2: Nothing nothing
3: String "world"
julia> eval(m1)
hello world
julia> m1 == m2
true
当然,如果您的代码是嵌套的,则必须在整个Expr
的AST上递归地替换其元素。
答案 3 :(得分:2)
您可以考虑定义以下函数,以比较两个表达式是否相等而忽略行号节点,从而实现所需的功能:
function cmpexpr(ex1::Expr, ex2::Expr)
ex1.head === ex2.head || return false
length(ex1.args) === length(ex2.args) || return false
for (a1, a2) in zip(ex1.args, ex2.args)
typeof(a1) === typeof(a2) || return false
if a1 isa Expr
cmpexpr(a1, a2) || return false
elseif !(a1 isa LineNumberNode)
isequal(a1, a2) || return false
end
end
return true
end