Hello,
I’m exploring an idea which may look funny. Please tell me if you thinks it’s impossible or useless.
My goal
I’d like to generate automatically (with metaprogramming I guess) functions which body and signature comes from an existing function “template” and then appending a return statement (return myvar
where myvar
can be decided in the code). Here is an illustration.
The function “template” model
is a model of physical system which computes many variables (only 3 (c
,d
,e
) in this dummy example).
function model(a,b)
c = 2*a
d = c+b
e = d^2
end
To provide more context, this model will be used in several optimization variants, like:
- minimize
d
- minimize
d
s.t.e
≤ 2 - minimize
e
+d
- …
These variants should be user selectable.
To support the variants without duplicating the code of model
, I’d like an easy way for the user my optimization tool to select the relevant output(s) of model
. So I’ve imagined I could have macro which could be invoked as:
@set_return model_retc model :c
And this would generate the function:
function model_retc(a,b) # function name set in macro invokation
# signature and body copy-pasted from `model`
c = 2*a
d = c+b
e = d^2
return c # returned variable(s) set in macro invokation
end
It’s not clear to me how to do this. I’ve searched two approaches:
- Get the AST of the template function, but I kind of understood that AST is defined for specific methods rather than the generic function (SO: Access the AST for generic functions in Julia)
- Get the source code of the template function, but I didn’t go all the way. Only, I found on SO How to print in REPL the code of functions in Julia? which seems to indicate that it’s not working for REPL-defined functions.
- Also, the
@less
macro is about opening the source in a pager, but I just want to get the source in a variable.
Also, I got from Write Julia macro that returns a function that to create a function in a macro, it is necessary to have the the content known at compile time, not at execution time. I think in my case all information is available in the source code.
Alternative without metaprogramming: is it good enough?
Since I don’t know how to achieve my goal with metaprogramming, I’m using an approach based on 1) returning all variables of potential interest and 2) select those in a wrapper.
The function which return “all” is:
function model_retall(a,b)
c = 2*a
d = c+b
e = d^2
return Dict(:c => c, :d => d, :e => e)
end
Then I can create (manually or with a short function factory):
function model_retc(a,b)
model_retall(a,b)[:c]
end
My questions on this metaprogramming-less approach are:
- Are there better alternatives than returning a
Dict
of variables?- This approach is actually insired by an existing Python tool which enforces a convention that all model functions should
return locals()
, i.e. all local variables?
- This approach is actually insired by an existing Python tool which enforces a convention that all model functions should
- Is there some performance issue related to returning many outputs kike in
model_retall
and then dropping most of them (e.g.d
ande
ends up being unnecessary to computec
)- in particular, in my optimization approach, I want to compute the gradient of
model_retc
with some AD package (ForwardDiff, Zygote, other…?)
- in particular, in my optimization approach, I want to compute the gradient of