Whenever I talk to someone about macros, I always suggest they start by looking at the expansion of the macro. But the default expansion isn’t super readable because of LineNumberNode’s, gensyms, etc.
So I almost always end up using MacroTools.prettify:
MacroTools.prettify(@macroexpand @everywhere x = 1)
Should Base Julia have the equivalent of this composition in it? It seems like it could make macros more accessible.
             
            
              
              
              6 Likes
            
            
           
          
            
            
              Agreed! I’ll just add that I sometimes prefer
 MacroTools.prewalk(rmlines, @macroexpand @everywhere x = 1)
to see the original variable names (even if they’re mangled) as this can give a much better idea of what’s going on for larger macros. A way to get the original symbols (unmangled) would be even better…
             
            
              
              
              3 Likes
            
            
           
          
            
            
              
This looks equivalent to Base.remove_linenums! unless I am missing something? It should be pretty trivial to support a kwarg to @macroexpand that just remove linenumbers (similar to e.g. @code_llvm which has debuginfo as a kwarg).
             
            
              
              
              2 Likes
            
            
           
          
            
            
              Nice, I didn’t know there was already a way to do it in Base!
This sounds great. Arguably the “brief” printout is more commonly needed than the verbose one, so maybe brief=true should even be the default?
             
            
              
              
              
            
            
           
          
            
            
              The MacroTools version catches some line-numbers that the Base one misses:
julia> Base.remove_linenums!(@macroexpand1 @assert 1 == @view A[1])
:(if 1 == #= REPL[57]:1 =# @view(A[1])
      nothing
  else
      Base.throw(Base.AssertionError("1 == #= REPL[57]:1 =# @view(A[1])"))
  end)
julia> MacroTools.prewalk(rmlines, @macroexpand1 @assert 1 == @view A[1])
:(if 1 == @view(A[1])
      nothing
  else
      Base.throw(Base.AssertionError("1 == #= REPL[58]:1 =# @view(A[1])"))
  end)
             
            
              
              
              1 Like
            
            
           
          
            
            
              I think that the best solution is to make MacroTools a standard library (ideally after stdlib version numbers are decoupled from Julia proper).
It has a lot of useful functionality, and is practically indispensable for working with macros in Julia.
             
            
              
              
              
            
            
           
          
            
            
              Yes, it doesn’t strip out LineNumberNodes from macrocall expressions. I think rmlines actually replaces those with nothing.