Sorry if this is a common question and I just missed the answer when searching around.
I’m trying to mimic the functionality of a macro by building up an expression similar to what it takes as input, calling the same function the macro calls, and then calling eval
on the resulting expression. I can’t quite seem to make this work, so was hoping for some advice on what to do differently.
We have the following macro in DiffEqBiological:
macro min_reaction_network(ex::Expr, p...)
min_coordinate(:min_reaction_network, MacroTools.striplines(ex), p, :no___noise___scaling)
end
Typical usage would be
network = @min_reaction_network begin
c1, X --> 2X
c2, X --> 0
end c1 c2
My understanding is that in the macro definition ex
corresponds to the begin
to end
block expression, and p
to a tuple of the symbols at the end (:c1,:c2,:c3)
.
I’m trying to create a package to read in a different network file format and output a min_reaction_network
. My approach was to try to build up an equivalent expression to what gets passed into min_coordinate
, and a similar parameter tuple, and then call eval
on what min_coordinate
returns. The issue is that I don’t seem to be able to quite figure out how to build this expression correctly.
For say the example above, can anyone show me how to build an equivalent expression to what the macro passes to min_coordinate
so that I can call it directly?
Thanks!
I’m not sure I understand exactly what you want to do, but maybe this approach would suit you.
First, modify your macro so that it does not call min_coordinate
, but only build its argument tuple:
macro min_reaction_network_2(ex::Expr, p...)
(:min_reaction_network, MacroTools.striplines(ex), p, :no___noise___scaling)
end
then, expand the macro call (a direct evaluation might work too):
julia> @macroexpand @min_reaction_network_2 begin
c1, X --> 2X
c2, X --> 0
end c1 c2
(:min_reaction_network, quote
(c1, $(Expr(:-->, :X, :(2X))))
(c2, $(Expr(:-->, :X, 0)))
end, (:c1, :c2), :no___noise___scaling)
this tuple should be what the macro passes to min_coordinates
Thanks for the help. I’d like to be able to do something like:
myexpr = min_coordinate(...)
eval(myexpr)
which I was hoping would mimic the functionality of the macro.
Using your tuple I still don’t seem to be able to do this:
mcargs = (:min_reaction_network, quote
(c1, $(Expr(:-->, :X, :(2X))))
(c2, $(Expr(:-->, :X, 0)))
end, (:c1, :c2), :no___noise___scaling)
myexpr = DiffEqBiological.min_coordinate(mcargs[1],MacroTools.striplines(mcargs[2]),mcargs[3],mcargs[4])
returns an expression, but calling eval(myexpr)
gives an invalid syntax error. Is this somehow related to the expression not being evaluated within the DiffEqBiological package?
At a higher level, I am trying to avoid building a giant string that contains the full macro command and just calling Meta.parse
and then eval
on it. i.e. avoid:
str = "@min_reaction_network begin
c1, X --> 2X
c2, X --> 0
end c1 c2 "
network = eval(Meta.parse(str))
That approach works fine, but I was hoping to just go directly from expressions to getting the network
out.
If there is a different approach that makes more sense to you please do let me know.