Help understanding use of macros over functions that return expressions

The docs are clear about how macros execute before the enclosing code is run, but I’m still having trouble imagining where this is necessary, when we already have functions that return expressions.

It’s easy to come up with examples like f_with_<> below a macro like @m_xy does the same thing as a function like f_xy. Are there some alternative examples where macros would be necessary or provide some performance benefit?

macro m_xy(op,x,y)
        return Expr(:call,op,x,y)
end

function f_xy(op,x,y)
        return Expr(:call,op,x,y)
end

function f_with_mac()
        @m_xy(+,a*x,a*y)
end

function f_with_func()
        eval(f_xy(+,a*x,a*y))
end

a = 2
x = 3
y = 4
@test f_with_mac() == eval(f_with_func())

calling eval on an AST runs that code at global scope.
Which has a bunch of problems.
But especially if your macro is supposed to do things like delcare some local variables, then you can’t do that with eval (since then they would be global variables).

4 Likes