Metaprogramming using Meta.parse + eval

Here’s an example of what I am trying to do:

src = ["function f(x) x^2 end",
         "function f(x) x^3 end",
         "function f(x) x^4 end"]
for s in src
    eval(Meta.parse(s))
    @show f(2)
end

This does not work.

The context is this: I want to automatically define multiple models that share a lot of code, so I am constructing their source as a string.
Now I want to loop over the functions (or their definitions) and fit them to data.

How can I actually do this? Or should I use a different approach?

1 Like

What do you mean it doesn’t work?

You are not creating multiple functions but that code should “work” as you are overriding the methods.

No matter what you need, you never need to construct their code as string. For sharing code, use a common function that all of them calls. For shared template, which your string approach couldn’t deal with anyway, splice your variable part into the code directly. In all cases, you should do metaprogramming on code not strings.

And if you meant after you did this loop you only have one f. Well, you need to create multiple functions instead of one. Either give them different names or use anonymous functions.

1 Like

Welcome!
You can use @eval to define programmatically functions without having to use strings, here is a code snippet:

import Base: +, -, *, /, ^
operations = (:+, :-, :*, :/, :^)
for op in operations
    @eval $op(c1:: MyType, a:: Number) = MyType(c1.x, $op.(c1.y, a))
end

Edit: added a reason for my post in the first line.

Sorry for being unclear: what I mean is that the output of

src = ["function f(x) x^2 end",
       "function f(x) x^3 end",
       "function f(x) x^4 end"]
for s in src
    eval(Meta.parse(s))
    @show f(2)
end

is not 4, 8, 16.

You are right though and I should find a way to define the models differently.

julia> src = ["function f(x) x^2 end",
                "function f(x) x^3 end",
                "function f(x) x^4 end"]
3-element Array{String,1}:
 "function f(x) x^2 end"
 "function f(x) x^3 end"
 "function f(x) x^4 end"

julia> for s in src
           eval(Meta.parse(s))
           @show f(2)
       end
f(2) = 4
f(2) = 8
f(2) = 16

It probably still won’t do what you want in other cases but I don’t see why this case won’t. More like you get a f somewhere / you didn’t paste the full code.

2 Likes

Oh dear… yes in a fresh session it works… sorry for the confusion on my part.

2 Likes