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 LineNumberNodes). 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.)