# Replacing eval(Meta.parse(...)) with macro

**URL:** <https://discourse.julialang.org/t/replacing-eval-meta-parse-with-macro/62788>\
**Category:** General Usage\
**Tags:** question, metaprogramming\
**Created:** [June 12, 2021, 10:23am UTC](https://discourse.julialang.org/t/replacing-eval-meta-parse-with-macro/62788 "2021-06-12T10:23:48Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![MartaVanin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/martavanin/32/14658_2.png) [@MartaVanin](https://discourse.julialang.org/u/MartaVanin)\
**Post date:** [June 12, 2021, 10:23am UTC](https://discourse.julialang.org/t/replacing-eval-meta-parse-with-macro/62788/1 "2021-06-12T10:23:48Z")

</div>

Hello,  
I want to push a number of anonymous functions to an array. Each function is largely the same but in some cases some addends are scalars instead of variables. Say that there are three different cases, like:  
case 1) f(x) = x[1]+x[3]+cos(x[1]-x[2])  
case 2) f(x) = x[1]+x[3]+cos(a) where a is a scalar  
case 3) f(x) = x[1]+x[3]+cos(x[1]-x[3])  
(in reality the function is way bigger).  
So, instead of writing something like this:

```julia
function_array = []
for case in cases
    if case.type == 1
      push!(functions_array, x->x[1]+x[3]+cos(x[1]-x[2]) )
   elseif case.type ==2

etc.

```

I figure I’d use metaprogramming and do

```julia
function_array = []
for case in cases
   if case.type == 1
      cos_arg = :(x[1]-x[2])
   elseif case.type == 2 
     cos_arg = :(a)
   else 
     cos_arg = :(x[1]-x[3])
   end
 push!(function_array, x->x[1]+x[3]+cos(eval(Meta.parse(cos_arg))) )
end

```

But then I realized that `eval(Meta.parse(...))` is in general a bad idea and `eval` only does it in the global scope, which is not good in my case.  
So I guess I should write a macro instead, but it’s something I never did and I am not sure on how to best approach this. I did read the metaprogramming section of the manual but I am still a bit confused, and could use some tips.

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [June 12, 2021, 10:34am UTC](https://discourse.julialang.org/t/replacing-eval-meta-parse-with-macro/62788/2 "2021-06-12T10:34:27Z")

</div>

Hmm, maybe MWE is incomplete, but it looks like you do not need metaprogramming. Functions are first-class citizens in Julia, so you can use them as lego blocks to build arbitrarily complicated expressions.

```julia
function_array = []
cases = [(; type = 1), (; type = 2), (; type = 3)]
a = 1
for case in cases
    f1 = if case.type == 1
        x -> x[1] - x[2]
    elseif case.type == 2
        x -> a
    else
        x -> x[1] + x[3]
    end
    push!(function_array, x -> x[1] + x[3] + cos(f1(x)))
end

```

and sanity check

```julia
julia> map(i -> function_array[i]([1, 4, 7]), 1:3)
3-element Vector{Float64}:
 7.010007503399555
 8.54030230586814
 7.854499966191386

```

---

<div class="post-metadata">

**Author:** ![MartaVanin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/martavanin/32/14658_2.png) [@MartaVanin](https://discourse.julialang.org/u/MartaVanin)\
**Post date:** [June 12, 2021, 12:43pm UTC](https://discourse.julialang.org/t/replacing-eval-meta-parse-with-macro/62788/3 "2021-06-12T12:43:35Z")

</div>

Thanks, that’s quite interesting and I did not know that!  
However, I am afraid that I have over-simplified my problem, so in my actual case this solution does not seem to work. Let me see if I can explain my problem a bit more in detail. I am trying to write a function more like the following (again with the eval(Meta.parse(…)) approach):

```julia
function func_name(connected_branches::Array, case, function_array::Array, angle_from, angle_to)
    ev_arg = eval ∘ Meta.parse ∘ string
    if case == 1
          cos_arg = :(deg2rad.([0, 120, -120])[c] - x[angle_to[br][d]]) # angle_from and angle_to are arrays of scalars
    else
        cos_arg = :(x[angle_from[c]] - x[angle_to[br][d]])
    end
   for c in 1:3
      push!(function_array, x->sum( (x[1]+x[2]+cos(ev_arg(cos_arg)) for d in 1:3 if d!=c) for br in connected_branches) )
   end
end

```

so, basically, if I try to apply the method you suggested directly, I get `UndefVarError: br not defined`, because this is somehow “nested” in the variable index.  
The inputs would look sort of like:

```julia
connected_branches = [1, 2]
case = 1
function_array = []
angle_from = [1, 2, 3]
angle_to = [[2, 4, 6], [1, 3, 5]]

```

I hope it is kind of clear and makes somewhat sense. Basically, `angle_to` and `angle_from` host the indexes of the variable array that I want to choose.

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [June 12, 2021, 12:58pm UTC](https://discourse.julialang.org/t/replacing-eval-meta-parse-with-macro/62788/4 "2021-06-12T12:58:33Z")

</div>

You can make `c`, `d` and `br` arguments of internal functions

```julia
function func_name(connected_branches::Array, case, function_array::Array, angle_from, angle_to)
   f1 = if case == 1
          (x, c, d, br) -> deg2rad.([0, 120, -120])[c] - x[angle_to[br][d]] # angle_from and angle_to are arrays of scalars
    else
        (x, c, d, br) -> x[angle_from[c]] - x[angle_to[br][d]]
    end
   for c in 1:3
      push!(function_array, x->sum( (x[1]+x[2]+cos(f1(x, c, d, br)) for d in 1:3 if d!=c) for br in connected_branches) )
   end
end

```

---

<div class="post-metadata">

**Author:** ![MartaVanin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/martavanin/32/14658_2.png) [@MartaVanin](https://discourse.julialang.org/u/MartaVanin)\
**Post date:** [June 12, 2021, 1:31pm UTC](https://discourse.julialang.org/t/replacing-eval-meta-parse-with-macro/62788/5 "2021-06-12T13:31:41Z")

</div>

works perfectly, thank you!
