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 LineNumberNode
s from macrocall
expressions. I think rmlines
actually replaces those with nothing
.