Is there any advice on whether it’s ok to mutate the input expressions to a macro? Is it better practice to create new Expr
objects? What are the pros and cons of mutating or not mutating?
Below is a simple example with a macro @declare
that takes a block of names and converts them into function stubs (e.g. function foo end
). The @declare1
macro mutates the input block expression, whereas the @declare2
macro creates a new block expression. They expand to the same output (including LineNumberNode
s). Is there a reason why I should prefer one over the other?
macro declare1(block)
for i in [2, 4]
block.args[i] = :(function $(esc(block.args[i])) end)
end
block
end
macro declare2(block)
stubs = map(block.args[[2, 4]]) do sym
:(function $(esc(sym)) end)
end
Expr(:block, block.args[1], stubs[1], block.args[3], stubs[2])
end
julia> @macroexpand @declare1 begin
foo
bar
end
quote
#= REPL[3]:2 =#
function foo end
#= REPL[3]:3 =#
function bar end
end
julia> @macroexpand @declare2 begin
foo
bar
end
quote
#= REPL[4]:2 =#
function foo end
#= REPL[4]:3 =#
function bar end
end
(Yes, I know block.args[[2, 4]]
allocates. That’s not the point of the question.)