TL DR: I have a macro in an external module, how do I enable the expression it executes after “return” to see variables declared in the scope in which the macro is called? Background at the end if you are interested.
I have this module
module test_module
export @test_macro
macro test_macro(ex)
return :(x -> $ex)
end
end
,basically the macro returns a function corresponding to the input expression. If I then have this code:
using test_module
f(x) = 2x
a = 2
f1 = @test_macro(2x)
f2 = @test_macro(f(x))
f3 = @test_macro(a*x)
println(f1(2))
println(f2(2))
println(f3(2))
I would expect all to print the value 4
. However only the first does, the other two gives me messages UndefVarError: f not defined
and UndefVarError: a not defined
. How would I write it if I want the macro to use code in the scope were I am executing it?
If I instead define the macro in the same scope it works fine:
macro test_macro(ex)
return :(x -> $ex)
end
f(x) = 2x
a = 2
f1 = @test_macro(2x)
f2 = @test_macro(f(x))
f3 = @test_macro(a*x)
println(f1(2))
println(f2(2))
println(f3(2))
writes
4
4
4
, just as I would expect.
(Background: )
I have a program which lets me input chemical reaction networks and then returns systems of differential equations to be used for simulating the network, after some initial interpretation of the input it returns:
return :(network_model($f, $g, $jumps))
(newtork_model is a structure containing functions f and g as well as a tuple of constant rate jumps.)
When I define the reaction system some of the reaction rates might be written as k_d1 etc. However when the macro returns the functions they cannot see the values of the variables (like k_d1). However if I rather than having a macro have a function which returns f, g and jumps as expressions, and then executes the expressions using eval they can include variables like k_d1. But there should be a way to do this in the macro without using a function and eval?