Generic function for stripping `LineNumberNode` in `Expr`(should be able to deal with :macrocalls)?












6















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: Array{Any}((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: 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


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.










share|improve this question





























    6















    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: Array{Any}((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: 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


    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.










    share|improve this question



























      6












      6








      6


      1






      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: Array{Any}((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: 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


      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.










      share|improve this question
















      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: Array{Any}((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: 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


      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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 15 '18 at 7:51







      Gnimuc

















      asked Nov 13 '18 at 4:49









      GnimucGnimuc

      4,77011739




      4,77011739
























          4 Answers
          4






          active

          oldest

          votes


















          2





          +100









          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.






          share|improve this answer
























          • 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











          • Base.remove_linenums! is exactly what I was looking for, so marked this as the answer.

            – Gnimuc
            Nov 21 '18 at 10:28



















          3














          Not built in, but MacroTools.jl has MacroTools.striplines(ex) which removes the LineNumberNodes from an expression.






          share|improve this answer
























          • 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











          • 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











          • 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



















          2














          Since your goal is to be able to compare Exprs maybe replace LineNumberNodes with nothing. This allows to make comparisons and the Exprs 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: Array{Any}((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.






          share|improve this answer































            2














            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





            share|improve this answer

























              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
              });


              }
              });














              draft saved

              draft discarded


















              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









              2





              +100









              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.






              share|improve this answer
























              • 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











              • Base.remove_linenums! is exactly what I was looking for, so marked this as the answer.

                – Gnimuc
                Nov 21 '18 at 10:28
















              2





              +100









              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.






              share|improve this answer
























              • 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











              • Base.remove_linenums! is exactly what I was looking for, so marked this as the answer.

                – Gnimuc
                Nov 21 '18 at 10:28














              2





              +100







              2





              +100



              2




              +100





              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.






              share|improve this answer













              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.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Nov 17 '18 at 14:31









              miguel razmiguel raz

              30615




              30615













              • 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











              • Base.remove_linenums! is exactly what I was looking for, so marked this as the answer.

                – Gnimuc
                Nov 21 '18 at 10:28



















              • 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











              • Base.remove_linenums! is exactly what I was looking for, so marked this as the answer.

                – Gnimuc
                Nov 21 '18 at 10:28

















              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













              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













              3














              Not built in, but MacroTools.jl has MacroTools.striplines(ex) which removes the LineNumberNodes from an expression.






              share|improve this answer
























              • 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











              • 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











              • 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
















              3














              Not built in, but MacroTools.jl has MacroTools.striplines(ex) which removes the LineNumberNodes from an expression.






              share|improve this answer
























              • 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











              • 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











              • 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














              3












              3








              3







              Not built in, but MacroTools.jl has MacroTools.striplines(ex) which removes the LineNumberNodes from an expression.






              share|improve this answer













              Not built in, but MacroTools.jl has MacroTools.striplines(ex) which removes the LineNumberNodes from an expression.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Nov 13 '18 at 7:24









              Chris RackauckasChris Rackauckas

              11.2k12346




              11.2k12346













              • 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











              • 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











              • 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



















              • 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











              • 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











              • 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

















              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











              2














              Since your goal is to be able to compare Exprs maybe replace LineNumberNodes with nothing. This allows to make comparisons and the Exprs 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: Array{Any}((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.






              share|improve this answer




























                2














                Since your goal is to be able to compare Exprs maybe replace LineNumberNodes with nothing. This allows to make comparisons and the Exprs 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: Array{Any}((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.






                share|improve this answer


























                  2












                  2








                  2







                  Since your goal is to be able to compare Exprs maybe replace LineNumberNodes with nothing. This allows to make comparisons and the Exprs 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: Array{Any}((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.






                  share|improve this answer













                  Since your goal is to be able to compare Exprs maybe replace LineNumberNodes with nothing. This allows to make comparisons and the Exprs 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: Array{Any}((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.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 13 '18 at 16:39









                  Przemyslaw SzufelPrzemyslaw Szufel

                  1,679111




                  1,679111























                      2














                      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





                      share|improve this answer






























                        2














                        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





                        share|improve this answer




























                          2












                          2








                          2







                          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





                          share|improve this answer















                          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






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Nov 15 '18 at 18:47

























                          answered Nov 15 '18 at 11:00









                          Bogumił KamińskiBogumił Kamiński

                          12.4k11220




                          12.4k11220






























                              draft saved

                              draft discarded




















































                              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.




                              draft saved


                              draft discarded














                              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





















































                              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







                              Popular posts from this blog

                              Full-time equivalent

                              Bicuculline

                              さくらももこ