Generic function for stripping `LineNumberNode` in `Expr`(should be able to deal with :macrocalls)?
Is there a build-in Julia function for stripping LineNumberNode
in Expr
? especially for macrocalls:
julia> ex = :(@foo 1)
:(#= REPL[5]:1 =# @foo 1)
julia> dump(ex)
Expr
head: Symbol macrocall
args: ArrayAny((3,))
1: Symbol @foo
2: LineNumberNode
line: Int64 1
file: Symbol REPL[5]
3: Int64 1
Tried MacroTools.striplines
, but
julia> ex = :(@foo 1+1)
:(#= REPL[7]:1 =# @foo 1 + 1)
julia> MacroTools.striplines(ex) |> dump
Expr
head: Symbol macrocall
args: ArrayAny((3,))
1: Symbol @foo
2: LineNumberNode
line: Int64 1
file: Symbol REPL[7]
3: Expr
head: Symbol call
args: ArrayAny((3,))
1: Symbol +
2: Int64 1
3: Int64 1
My use-case is to compare two different exprs constructed in different files(so different line number info). My current workaround is to explicitly write Expr(:macrocall, Symbol("@foo"), nothing, :(1+1)) which is a little bit verbose.
julia-lang
add a comment |
Is there a build-in Julia function for stripping LineNumberNode
in Expr
? especially for macrocalls:
julia> ex = :(@foo 1)
:(#= REPL[5]:1 =# @foo 1)
julia> dump(ex)
Expr
head: Symbol macrocall
args: ArrayAny((3,))
1: Symbol @foo
2: LineNumberNode
line: Int64 1
file: Symbol REPL[5]
3: Int64 1
Tried MacroTools.striplines
, but
julia> ex = :(@foo 1+1)
:(#= REPL[7]:1 =# @foo 1 + 1)
julia> MacroTools.striplines(ex) |> dump
Expr
head: Symbol macrocall
args: ArrayAny((3,))
1: Symbol @foo
2: LineNumberNode
line: Int64 1
file: Symbol REPL[7]
3: Expr
head: Symbol call
args: ArrayAny((3,))
1: Symbol +
2: Int64 1
3: Int64 1
My use-case is to compare two different exprs constructed in different files(so different line number info). My current workaround is to explicitly write Expr(:macrocall, Symbol("@foo"), nothing, :(1+1)) which is a little bit verbose.
julia-lang
add a comment |
Is there a build-in Julia function for stripping LineNumberNode
in Expr
? especially for macrocalls:
julia> ex = :(@foo 1)
:(#= REPL[5]:1 =# @foo 1)
julia> dump(ex)
Expr
head: Symbol macrocall
args: ArrayAny((3,))
1: Symbol @foo
2: LineNumberNode
line: Int64 1
file: Symbol REPL[5]
3: Int64 1
Tried MacroTools.striplines
, but
julia> ex = :(@foo 1+1)
:(#= REPL[7]:1 =# @foo 1 + 1)
julia> MacroTools.striplines(ex) |> dump
Expr
head: Symbol macrocall
args: ArrayAny((3,))
1: Symbol @foo
2: LineNumberNode
line: Int64 1
file: Symbol REPL[7]
3: Expr
head: Symbol call
args: ArrayAny((3,))
1: Symbol +
2: Int64 1
3: Int64 1
My use-case is to compare two different exprs constructed in different files(so different line number info). My current workaround is to explicitly write Expr(:macrocall, Symbol("@foo"), nothing, :(1+1)) which is a little bit verbose.
julia-lang
Is there a build-in Julia function for stripping LineNumberNode
in Expr
? especially for macrocalls:
julia> ex = :(@foo 1)
:(#= REPL[5]:1 =# @foo 1)
julia> dump(ex)
Expr
head: Symbol macrocall
args: ArrayAny((3,))
1: Symbol @foo
2: LineNumberNode
line: Int64 1
file: Symbol REPL[5]
3: Int64 1
Tried MacroTools.striplines
, but
julia> ex = :(@foo 1+1)
:(#= REPL[7]:1 =# @foo 1 + 1)
julia> MacroTools.striplines(ex) |> dump
Expr
head: Symbol macrocall
args: ArrayAny((3,))
1: Symbol @foo
2: LineNumberNode
line: Int64 1
file: Symbol REPL[7]
3: Expr
head: Symbol call
args: ArrayAny((3,))
1: Symbol +
2: Int64 1
3: Int64 1
My use-case is to compare two different exprs constructed in different files(so different line number info). My current workaround is to explicitly write Expr(:macrocall, Symbol("@foo"), nothing, :(1+1)) which is a little bit verbose.
julia-lang
julia-lang
edited Nov 15 '18 at 7:51
Gnimuc
asked Nov 13 '18 at 4:49
GnimucGnimuc
4,82511839
4,82511839
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
The built-in function is 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
Credit to Alex Arslan for reminding me of it.
1
thanks, this is what I was looking for, but it still doesn't work for macrocallsBase.remove_linenums!(:(@foo 1+1))
. I realized that theLineNumberNode
is mandatory when constructing macrocalls(don't know why), so it cannot be simply removed. a workaround is to set it to nothing like @Przemyslaw Szufel did in his answer.
– Gnimuc
Nov 18 '18 at 1:40
1
Base.remove_linenums!
is exactly what I was looking for, so marked this as the answer.
– Gnimuc
Nov 21 '18 at 10:28
add a comment |
Not built in, but MacroTools.jl has MacroTools.striplines(ex)
which removes the LineNumberNodes
from an expression.
no effect on macrocalls:MacroTools.striplines(:(@foo 1+1)) #-> :(#= REPL[5]:1 =# @foo 1 + 1)
– Gnimuc
Nov 13 '18 at 9:27
You have tomacroexpand
that interior macro first if you want to strip the lines of its resulting expression.
– Chris Rackauckas
Nov 13 '18 at 9:47
to be clear, what I want is actually to strip theLineNumberNode
of this:(@foo 1+1)
expression, the expected result should beExpr(:macrocall, Symbol("@foo"), nothing, :(1+1))
. I don't know why macrocalls needs a LineNumberNode to get constructed.
– Gnimuc
Nov 13 '18 at 10:37
Did you not tryMacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
orMacroTools.striplines(:(@macroexpand @foo 1+1)))
?
– Chris Rackauckas
Nov 13 '18 at 12:53
the problem is that at the time when stripping the line number,@foo
is not defined yet, soMacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
fails in this case.
– Gnimuc
Nov 13 '18 at 12:57
|
show 2 more comments
Since your goal is to be able to compare Expr
s maybe replace LineNumberNode
s with nothing
. This allows to make comparisons and the Expr
s still work. See the example below:
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: ArrayAny((3,))
1: Symbol @hello
2: Nothing nothing
3: String "world"
julia> eval(m1)
hello world
julia> m1 == m2
true
Of course if your code is nested you will have to make the replace its elements recursively over the entire Expr
's AST.
add a comment |
You can consider defining the following function to achieve what you want by comparing two expressions for equality ignoring line number nodes:
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
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53274001%2fgeneric-function-for-stripping-linenumbernode-in-exprshould-be-able-to-deal%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
The built-in function is 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
Credit to Alex Arslan for reminding me of it.
1
thanks, this is what I was looking for, but it still doesn't work for macrocallsBase.remove_linenums!(:(@foo 1+1))
. I realized that theLineNumberNode
is mandatory when constructing macrocalls(don't know why), so it cannot be simply removed. a workaround is to set it to nothing like @Przemyslaw Szufel did in his answer.
– Gnimuc
Nov 18 '18 at 1:40
1
Base.remove_linenums!
is exactly what I was looking for, so marked this as the answer.
– Gnimuc
Nov 21 '18 at 10:28
add a comment |
The built-in function is 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
Credit to Alex Arslan for reminding me of it.
1
thanks, this is what I was looking for, but it still doesn't work for macrocallsBase.remove_linenums!(:(@foo 1+1))
. I realized that theLineNumberNode
is mandatory when constructing macrocalls(don't know why), so it cannot be simply removed. a workaround is to set it to nothing like @Przemyslaw Szufel did in his answer.
– Gnimuc
Nov 18 '18 at 1:40
1
Base.remove_linenums!
is exactly what I was looking for, so marked this as the answer.
– Gnimuc
Nov 21 '18 at 10:28
add a comment |
The built-in function is 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
Credit to Alex Arslan for reminding me of it.
The built-in function is 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
Credit to Alex Arslan for reminding me of it.
answered Nov 17 '18 at 14:31
miguel razmiguel raz
31615
31615
1
thanks, this is what I was looking for, but it still doesn't work for macrocallsBase.remove_linenums!(:(@foo 1+1))
. I realized that theLineNumberNode
is mandatory when constructing macrocalls(don't know why), so it cannot be simply removed. a workaround is to set it to nothing like @Przemyslaw Szufel did in his answer.
– Gnimuc
Nov 18 '18 at 1:40
1
Base.remove_linenums!
is exactly what I was looking for, so marked this as the answer.
– Gnimuc
Nov 21 '18 at 10:28
add a comment |
1
thanks, this is what I was looking for, but it still doesn't work for macrocallsBase.remove_linenums!(:(@foo 1+1))
. I realized that theLineNumberNode
is mandatory when constructing macrocalls(don't know why), so it cannot be simply removed. a workaround is to set it to nothing like @Przemyslaw Szufel did in his answer.
– Gnimuc
Nov 18 '18 at 1:40
1
Base.remove_linenums!
is exactly what I was looking for, so marked this as the answer.
– Gnimuc
Nov 21 '18 at 10:28
1
1
thanks, this is what I was looking for, but it still doesn't work for macrocalls
Base.remove_linenums!(:(@foo 1+1))
. I realized that the LineNumberNode
is mandatory when constructing macrocalls(don't know why), so it cannot be simply removed. a workaround is to set it to nothing like @Przemyslaw Szufel did in his answer.– Gnimuc
Nov 18 '18 at 1:40
thanks, this is what I was looking for, but it still doesn't work for macrocalls
Base.remove_linenums!(:(@foo 1+1))
. I realized that the LineNumberNode
is mandatory when constructing macrocalls(don't know why), so it cannot be simply removed. a workaround is to set it to nothing like @Przemyslaw Szufel did in his answer.– Gnimuc
Nov 18 '18 at 1:40
1
1
Base.remove_linenums!
is exactly what I was looking for, so marked this as the answer.– Gnimuc
Nov 21 '18 at 10:28
Base.remove_linenums!
is exactly what I was looking for, so marked this as the answer.– Gnimuc
Nov 21 '18 at 10:28
add a comment |
Not built in, but MacroTools.jl has MacroTools.striplines(ex)
which removes the LineNumberNodes
from an expression.
no effect on macrocalls:MacroTools.striplines(:(@foo 1+1)) #-> :(#= REPL[5]:1 =# @foo 1 + 1)
– Gnimuc
Nov 13 '18 at 9:27
You have tomacroexpand
that interior macro first if you want to strip the lines of its resulting expression.
– Chris Rackauckas
Nov 13 '18 at 9:47
to be clear, what I want is actually to strip theLineNumberNode
of this:(@foo 1+1)
expression, the expected result should beExpr(:macrocall, Symbol("@foo"), nothing, :(1+1))
. I don't know why macrocalls needs a LineNumberNode to get constructed.
– Gnimuc
Nov 13 '18 at 10:37
Did you not tryMacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
orMacroTools.striplines(:(@macroexpand @foo 1+1)))
?
– Chris Rackauckas
Nov 13 '18 at 12:53
the problem is that at the time when stripping the line number,@foo
is not defined yet, soMacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
fails in this case.
– Gnimuc
Nov 13 '18 at 12:57
|
show 2 more comments
Not built in, but MacroTools.jl has MacroTools.striplines(ex)
which removes the LineNumberNodes
from an expression.
no effect on macrocalls:MacroTools.striplines(:(@foo 1+1)) #-> :(#= REPL[5]:1 =# @foo 1 + 1)
– Gnimuc
Nov 13 '18 at 9:27
You have tomacroexpand
that interior macro first if you want to strip the lines of its resulting expression.
– Chris Rackauckas
Nov 13 '18 at 9:47
to be clear, what I want is actually to strip theLineNumberNode
of this:(@foo 1+1)
expression, the expected result should beExpr(:macrocall, Symbol("@foo"), nothing, :(1+1))
. I don't know why macrocalls needs a LineNumberNode to get constructed.
– Gnimuc
Nov 13 '18 at 10:37
Did you not tryMacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
orMacroTools.striplines(:(@macroexpand @foo 1+1)))
?
– Chris Rackauckas
Nov 13 '18 at 12:53
the problem is that at the time when stripping the line number,@foo
is not defined yet, soMacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
fails in this case.
– Gnimuc
Nov 13 '18 at 12:57
|
show 2 more comments
Not built in, but MacroTools.jl has MacroTools.striplines(ex)
which removes the LineNumberNodes
from an expression.
Not built in, but MacroTools.jl has MacroTools.striplines(ex)
which removes the LineNumberNodes
from an expression.
answered Nov 13 '18 at 7:24
Chris RackauckasChris Rackauckas
11.2k12446
11.2k12446
no effect on macrocalls:MacroTools.striplines(:(@foo 1+1)) #-> :(#= REPL[5]:1 =# @foo 1 + 1)
– Gnimuc
Nov 13 '18 at 9:27
You have tomacroexpand
that interior macro first if you want to strip the lines of its resulting expression.
– Chris Rackauckas
Nov 13 '18 at 9:47
to be clear, what I want is actually to strip theLineNumberNode
of this:(@foo 1+1)
expression, the expected result should beExpr(:macrocall, Symbol("@foo"), nothing, :(1+1))
. I don't know why macrocalls needs a LineNumberNode to get constructed.
– Gnimuc
Nov 13 '18 at 10:37
Did you not tryMacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
orMacroTools.striplines(:(@macroexpand @foo 1+1)))
?
– Chris Rackauckas
Nov 13 '18 at 12:53
the problem is that at the time when stripping the line number,@foo
is not defined yet, soMacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
fails in this case.
– Gnimuc
Nov 13 '18 at 12:57
|
show 2 more comments
no effect on macrocalls:MacroTools.striplines(:(@foo 1+1)) #-> :(#= REPL[5]:1 =# @foo 1 + 1)
– Gnimuc
Nov 13 '18 at 9:27
You have tomacroexpand
that interior macro first if you want to strip the lines of its resulting expression.
– Chris Rackauckas
Nov 13 '18 at 9:47
to be clear, what I want is actually to strip theLineNumberNode
of this:(@foo 1+1)
expression, the expected result should beExpr(:macrocall, Symbol("@foo"), nothing, :(1+1))
. I don't know why macrocalls needs a LineNumberNode to get constructed.
– Gnimuc
Nov 13 '18 at 10:37
Did you not tryMacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
orMacroTools.striplines(:(@macroexpand @foo 1+1)))
?
– Chris Rackauckas
Nov 13 '18 at 12:53
the problem is that at the time when stripping the line number,@foo
is not defined yet, soMacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
fails in this case.
– Gnimuc
Nov 13 '18 at 12:57
no effect on macrocalls:
MacroTools.striplines(:(@foo 1+1)) #-> :(#= REPL[5]:1 =# @foo 1 + 1)
– Gnimuc
Nov 13 '18 at 9:27
no effect on macrocalls:
MacroTools.striplines(:(@foo 1+1)) #-> :(#= REPL[5]:1 =# @foo 1 + 1)
– Gnimuc
Nov 13 '18 at 9:27
You have to
macroexpand
that interior macro first if you want to strip the lines of its resulting expression.– Chris Rackauckas
Nov 13 '18 at 9:47
You have to
macroexpand
that interior macro first if you want to strip the lines of its resulting expression.– Chris Rackauckas
Nov 13 '18 at 9:47
to be clear, what I want is actually to strip the
LineNumberNode
of this :(@foo 1+1)
expression, the expected result should be Expr(:macrocall, Symbol("@foo"), nothing, :(1+1))
. I don't know why macrocalls needs a LineNumberNode to get constructed.– Gnimuc
Nov 13 '18 at 10:37
to be clear, what I want is actually to strip the
LineNumberNode
of this :(@foo 1+1)
expression, the expected result should be Expr(:macrocall, Symbol("@foo"), nothing, :(1+1))
. I don't know why macrocalls needs a LineNumberNode to get constructed.– Gnimuc
Nov 13 '18 at 10:37
Did you not try
MacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
or MacroTools.striplines(:(@macroexpand @foo 1+1)))
?– Chris Rackauckas
Nov 13 '18 at 12:53
Did you not try
MacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
or MacroTools.striplines(:(@macroexpand @foo 1+1)))
?– Chris Rackauckas
Nov 13 '18 at 12:53
the problem is that at the time when stripping the line number,
@foo
is not defined yet, so MacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
fails in this case.– Gnimuc
Nov 13 '18 at 12:57
the problem is that at the time when stripping the line number,
@foo
is not defined yet, so MacroTools.striplines(macroexpand(Main,:(@foo 1+1)))
fails in this case.– Gnimuc
Nov 13 '18 at 12:57
|
show 2 more comments
Since your goal is to be able to compare Expr
s maybe replace LineNumberNode
s with nothing
. This allows to make comparisons and the Expr
s still work. See the example below:
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: ArrayAny((3,))
1: Symbol @hello
2: Nothing nothing
3: String "world"
julia> eval(m1)
hello world
julia> m1 == m2
true
Of course if your code is nested you will have to make the replace its elements recursively over the entire Expr
's AST.
add a comment |
Since your goal is to be able to compare Expr
s maybe replace LineNumberNode
s with nothing
. This allows to make comparisons and the Expr
s still work. See the example below:
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: ArrayAny((3,))
1: Symbol @hello
2: Nothing nothing
3: String "world"
julia> eval(m1)
hello world
julia> m1 == m2
true
Of course if your code is nested you will have to make the replace its elements recursively over the entire Expr
's AST.
add a comment |
Since your goal is to be able to compare Expr
s maybe replace LineNumberNode
s with nothing
. This allows to make comparisons and the Expr
s still work. See the example below:
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: ArrayAny((3,))
1: Symbol @hello
2: Nothing nothing
3: String "world"
julia> eval(m1)
hello world
julia> m1 == m2
true
Of course if your code is nested you will have to make the replace its elements recursively over the entire Expr
's AST.
Since your goal is to be able to compare Expr
s maybe replace LineNumberNode
s with nothing
. This allows to make comparisons and the Expr
s still work. See the example below:
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: ArrayAny((3,))
1: Symbol @hello
2: Nothing nothing
3: String "world"
julia> eval(m1)
hello world
julia> m1 == m2
true
Of course if your code is nested you will have to make the replace its elements recursively over the entire Expr
's AST.
answered Nov 13 '18 at 16:39
Przemyslaw SzufelPrzemyslaw Szufel
1,729111
1,729111
add a comment |
add a comment |
You can consider defining the following function to achieve what you want by comparing two expressions for equality ignoring line number nodes:
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
add a comment |
You can consider defining the following function to achieve what you want by comparing two expressions for equality ignoring line number nodes:
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
add a comment |
You can consider defining the following function to achieve what you want by comparing two expressions for equality ignoring line number nodes:
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
You can consider defining the following function to achieve what you want by comparing two expressions for equality ignoring line number nodes:
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
edited Nov 15 '18 at 18:47
answered Nov 15 '18 at 11:00
Bogumił KamińskiBogumił Kamiński
12.8k11220
12.8k11220
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53274001%2fgeneric-function-for-stripping-linenumbernode-in-exprshould-be-able-to-deal%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown