Not-so-unusual Macro issues

Hello all. I’m having some macro-related issues. I’d like, if it’s even possible, to store the Expression of a function defined by the user, so I can write it to a file and use it elsewhere. I imagined that this would be most ergonomic for the user if it worked something like this, if it’s even possible:

module Test

mutable struct StoresFunction
    stored_func::Union{Nothing, Expr}
end

macro capture_function(sf, f)
  return quote
    $(esc(sf)).stored_func = $(esc(f))
  end
end

end

then from the point where this is called:

sf = Test.StoresFunction(nothing)

Test.@capture_function sf function tf(i::Int) i + 1 end

Which, ideally - though sadly not in this reality - stores the function expression down in the sf variable.

I feel that this might be quite close to working, but the compiler has no respect for my notions of ‘close to working’ and tells me:
MethodError: Cannot convert an object of type typeof(tf) to an object of type Expr
I have spent about two hours in trial and error, more or less randomly inserting $ and esc all over the place. Could anyone who actually understands what they are doing please lend a hand?

$(esc(f)) evaluates the expression f, so it is not an expression anymore, but a function. To avoid this, you can build the sf.stored_func = f expression yourself:

macro capture_function(sf, f)
    Expr(:(=), :($(esc(sf)).stored_func), Expr(:quote, f))
end
3 Likes

Thank you. That works great!