# Pass expression to manipulate local variable

**URL:** <https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652>\
**Category:** New to Julia\
**Tags:** question, metaprogramming\
**Created:** [April 18, 2022, 8:15pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652 "2022-04-18T20:15:32Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![FireCrumb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/firecrumb/32/35370_2.png) [@FireCrumb](https://discourse.julialang.org/u/FireCrumb)\
**Post date:** [April 18, 2022, 8:15pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/1 "2022-04-18T20:15:32Z")

</div>

Hi! I want to pass an `Expr` to a function, so it will be able to interact with _local variables_ inside the function.

What is the correct way to construct such an expression?

Here’s the basic structure of my function that accepts the expression “hook”:

```julia
function ex_v(v_init::Integer, hook::Expr)
    v = v_init
    eval(hook)
    return v
end

```

Tried the following, but I must be missing something basic, as none of them work.

```julia
ex_v(0, :(v = v+1)) # UndefVarError: v not defined
ex_v(0, :(:v = :v+1)) # syntax: invalid assignment location ":v"
ex_v(0, :($v = $v+1)) # UndefVarError: v not defined

```

---

<div class="post-metadata">

**Author:** ![FireCrumb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/firecrumb/32/35370_2.png) [@FireCrumb](https://discourse.julialang.org/u/FireCrumb)\
**Post date:** [April 18, 2022, 8:35pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/2 "2022-04-18T20:35:39Z")

</div>

According to an answer in another thread

> `eval` always happens at _global scope_

So the question remains: how to pass an `Expr` to work on _local scope_?

> [@Metaprogramming & variable scope](https://discourse.julialang.org/t/metaprogramming-variable-scope/25819):
>
> I have some function as such: function somefunction(df::AbstractDataFrame, indexcols::Array{Symbol,1}) ... dummydf = similar(df,0) for col in indexcols dummydf[col] = [] @eval $col = unique(df[$(QuoteNode(col))]) end ... return dummydf end For the @eval statement in the for loop, it’s telling me that df is not defined. I’m guessing that it’s looking for df within the scope of the eval statement. I tried wrapping the df in QuoteNode, but that didn’t work either.…

---

<div class="post-metadata">

**Author:** ![FireCrumb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/firecrumb/32/35370_2.png) [@FireCrumb](https://discourse.julialang.org/u/FireCrumb)\
**Post date:** [April 18, 2022, 8:38pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/3 "2022-04-18T20:38:47Z")

</div>

Some other similar questions:

- [Declaring top level variables in Julia using metaprogramming - Stack Overflow](https://stackoverflow.com/questions/26071317/declaring-top-level-variables-in-julia-using-metaprogramming)
- [julia - Evaluate expression with local variables - Stack Overflow](https://stackoverflow.com/questions/49200456/evaluate-expression-with-local-variables)
- [Julia local variable not defined in expression eval - Stack Overflow](https://stackoverflow.com/questions/60105828/julia-local-variable-not-defined-in-expression-eval)
- [Julia global variable in quote expression throws UndefVarError - Stack Overflow](https://stackoverflow.com/questions/67344880/julia-global-variable-in-quote-expression-throws-undefvarerror)

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [April 18, 2022, 8:45pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/4 "2022-04-18T20:45:22Z")

</div>

> [@FireCrumb](#):
>
> So the question remains: how to pass an `Expr` to work on _local scope_ ?

You basically can’t do that but depending on what you need to accomplish, the suggestions here might be useful: [Passing a string into function as a expression - #14 by GunnarFarneback](https://discourse.julialang.org/t/passing-a-string-into-function-as-a-expression/31625/14).

---

<div class="post-metadata">

**Author:** ![FireCrumb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/firecrumb/32/35370_2.png) [@FireCrumb](https://discourse.julialang.org/u/FireCrumb)\
**Post date:** [April 18, 2022, 8:54pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/5 "2022-04-18T20:54:27Z")

</div>

Trying to build upon the solution suggested in [Declaring top level variables in Julia using metaprogramming - Stack Overflow](https://stackoverflow.com/a/26071597), but not getting expected result, the Expr inside the function inside the macro doesn’t seem to be executed. What am I doing wrong?

```julia
@eval function f(t, hook)
    x = 0
    for i in 1:t
        esc(hook)
    end
    return x
end

f(100, :(:x = :x+1))

```

This returns `0` and not `100`, meaning the `hook` isn’t being called.

---

<div class="post-metadata">

**Author:** ![FireCrumb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/firecrumb/32/35370_2.png) [@FireCrumb](https://discourse.julialang.org/u/FireCrumb)\
**Post date:** [April 18, 2022, 9:00pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/6 "2022-04-18T21:00:28Z")

</div>

> [@GunnarFarneback](#):
>
> You basically can’t do that but depending on what you need to accomplish, the suggestions here might be useful: [Passing a string into function as a expression - #14 by GunnarFarneback](https://discourse.julialang.org/t/passing-a-string-into-function-as-a-expression/31625/14).

Trying to adapt it to my use-case, and can’t get it to work:

```julia
function f(t, expr_str)
    ex = Meta.parse(expr_str)
    return @eval begin
        x = 0
        for i in 1:$t
            $ex
        end
        return x
    end 
end

f(100, ":(:x = :x+1)")

```

It returns 0 rather than 100, which means the expression doesn’t manipulate the local `x` variable.

Can you please help me adjust the code so the Expr accesses the variables in the local scope?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 18, 2022, 9:04pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/7 "2022-04-18T21:04:27Z")

</div>

> [@FireCrumb](#):
>
> Hi! I want to pass an `Expr` to a function, so it will be able to interact with _local variables_ inside the function. What is the correct way to construct such an expression?

Even if you got this to work, the performance would be terrible, the maintainability would be worse (the external caller would have to know the implementation details of the function they are calling), and in general this sounds like a classic [xy problem](https://xyproblem.info/).

What is your ultimate goal here? What kind of functionality do you want to achieve?

---

<div class="post-metadata">

**Author:** ![FireCrumb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/firecrumb/32/35370_2.png) [@FireCrumb](https://discourse.julialang.org/u/FireCrumb)\
**Post date:** [April 18, 2022, 9:32pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/8 "2022-04-18T21:32:06Z")

</div>

> [@stevengj](#):
>
> What is your ultimate goal here? What kind of functionality do you want to achieve?

My ultimate goal is quite complex and well beyond the scope of a single question 😅

I’m searching, using Evolutionary Algorithm, for different implementations for a function to achieve a certain objective.

My search _candidates_ are pieces of code represented as `Expr` objects, which work on a predefined set of variables of known types and names. So the “external caller” can be assumed to be fully aware of the “internal” implementation, that’s not a problem.

In the simple code example above, the variables are `[v::Integer]`, but in the real use-case there are many variables of different names and types.

And the example candidate `Expr` is `v=v+1`, and the objective is for v to be 100.

Again, of course in the real case, there are more variables and a more complex and realistic optimization problem.

I want to _evaluate_ `ex_v()` with different `hook` candidates, and get the “score” (return value) for each of them.

Please let me know if this explanation makes things more clear. Thanks for the help!

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 18, 2022, 9:42pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/9 "2022-04-18T21:42:32Z")

</div>

> [@FireCrumb](#):
>
> My search _candidates_ are pieces of code represented as `Expr` objects, which work on a predefined set of variables of known types and names. So the “external caller” can be assumed to be fully aware of the “internal” implementation, that’s not a problem.

In other words, your `Expr` objects are the body of a function `(v1,v2,...) -> body`? where `v1,v2,...` are some set of known variables, and the function body returns some value, or maybe the new values of the variables?

One way is to let `f = eval(:((v1,v2) -> $body))` to get a function `f(v1,v2)` and then work with that subsequently. Or `f = eval(:((v1,v2) -> ($body; return v1,v2)))` if you want to return the new values of the variables.

This way you get a function object that can be compiled and run quickly if you want to run it many times for different values of the parameters if needed.

(Conversely, if you only want to evaluate each expression a few times, it might not be worth paying the cost of compiling the expression and you might want to write a little interpreter instead, or use something like [JuliaInterpreter.jl](https://github.com/JuliaDebug/JuliaInterpreter.jl).)

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 18, 2022, 9:46pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/10 "2022-04-18T21:46:12Z")

</div>

For example:

```julia
julia> function ex_v(v_init::Integer, hook::Expr)
           f = eval(:(v -> ($hook; v)))
           return Base.invokelatest(f, v_init)
       end
ex_v (generic function with 1 method)

julia> ex_v(0, :(v = v+1))
1

```

Again, however, this is a pretty slow way to evaluate an expression unless are calling `f` many times and not just once as is done here, and you’d probably be better off with an interpreter if you only need a few evaluations.

More generally, the `Expr` data structure is not really designed for rapid evaluation and manipulation. In a GA situation like you describe, you’d likely be better off devising a custom byte-code representation for the specific types of expression you want to search, and work with that.

---

<div class="post-metadata">

**Author:** ![FireCrumb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/firecrumb/32/35370_2.png) [@FireCrumb](https://discourse.julialang.org/u/FireCrumb)\
**Post date:** [April 20, 2022, 8:03am UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/11 "2022-04-20T08:03:39Z")

</div>

Thanks for all the helpful comments!

Important note about Genetic Algorithms (GA):  
**While _defining_ new function (GA ‘solution’) should be fast, it will be executed many times, so _execution/evaluation_ is far more important**.

> [@stevengj](#):
>
> More generally, the `Expr` data structure is not really designed for rapid evaluation and manipulation. In a GA situation like you describe, you’d likely be better off devising a custom byte-code representation for the specific types of expression you want to search, and work with that.

Well, yes I could do something like writing LLVM directly.  
_However_, in my use-case, I _would_ like to use Julia’s compilation and optimization for the evaluated code – it will start from an Expr so no expensive parsing needed, but many more further processing is actually welcome.

* * *

TL;DR: I’ve progressed a lot further, but still need to get dynamic execution much faster. See all details below.

* * *

The most simple code that accomplishes what I was looking for:

```julia
function get_ex_v(v_init::Integer, hook::Expr)
    quote
        v = $v_init
        x = 10
        y = 5
        $hook
        return z
    end
end

hook1 = :(z = v + x*y)
hook2 = :(z = v + x/y)

@assert eval(get_ex_v(1, hook1)) == (1 + 10*5)
@assert eval(get_ex_v(2, hook2)) == (2 + 10/5)

```

However, as @stevengj mentioned very correctly, the performance is horrible when using `eval()` many times to run the code:

```julia
using BenchmarkTools

function f1(v_init)
    v = v_init
    x = 10
    y = 5
    z = v + x*y
    return z
end

@benchmark f1(1)

```

```julia
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min … max): 0.010 ns … 0.031 ns ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 0.020 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 0.020 ns ± 0.002 ns ┊ GC (mean ± σ): 0.00% ± 0.00%

  ▁ █ ▃ ▁ ▁
  █▁▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ █
  0.01 ns Histogram: log(frequency) by time 0.03 ns <

```

but

```julia
ex1 = get_ex_v(1, hook1)

@benchmark eval(ex1)

```

gives

```julia
BenchmarkTools.Trial: 10000 samples with 1 evaluation.
 Range (min … max): 118.164 μs … 593.284 μs ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 123.804 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 126.664 μs ± 25.473 μs ┊ GC (mean ± σ): 0.00% ± 0.00%

   ▁█▃ ▁▃▄▁                                                     
  ▃███▅▅████▆▄▄▃▃▂▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▂▂▂▂ ▃
  118 μs Histogram: frequency by time 168 μs <

 Memory estimate: 3.22 KiB, allocs estimate: 61.

```

So actually I should call `eval()` _once_ (for each GA candidate)

```julia
function define_ex_v_func(hook::Expr, funcname)
    quote
        function $funcname(v_init::Integer)
            v = v_init
            x = 10
            y = 5
            z = 400
            $hook
            return z
        end
    end
end

eval(define_ex_v_func(hook1, :ex_v1))
eval(define_ex_v_func(hook2, :ex_v2))

@assert ex_v1(1) == (401 + 10*5)
@assert ex_v2(2) == (402 + 10/5)

```

and then execute it directly, which is fast:

```julia
@benchmark ex_v1(1)

```

```julia
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min … max): 0.010 ns … 0.291 ns ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 0.020 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 0.021 ns ± 0.004 ns ┊ GC (mean ± σ): 0.00% ± 0.00%

                              █ ▃ ▃ ▁
  ▇▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ █
  0.01 ns Histogram: log(frequency) by time 0.03 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

```

But, wait!  
I want to create many dynamic functions in runtime.

So, let’s create a random function name

> <https://stackoverflow.com/questions/56453509/how-to-generate-random-alphanumeric-string-in-julia/56453765#56453765>

And refer to its symbol

> <https://stackoverflow.com/questions/34016768/julia-invoke-a-function-by-a-given-string/34023458#34023458>

So I got to this:

```julia
using Random

function create_ex_v_func(hook::Expr)
    new_func_name = Symbol("ex_v_" * randstring(12))

    eval(quote
        function $new_func_name(v_init::Integer)
            v = v_init
            x = 10
            y = 5
            z = 400
            $hook
            return z
        end
    end)

    return getfield(Main, new_func_name)
end

ex_v_f1 = create_ex_v_func(hook1)
ex_v_f2 = create_ex_v_func(hook2)

@assert ex_v_f1(1) == (401 + 10*5)
@assert ex_v_f2(2) == (402 + 10/5)

```

Finally resolved? Not quite…

There’s a big difference between the performance of calling the function directly by name, and invoking it through a pointer:

```julia
@benchmark ex_v_f1(5)

```

```julia
BenchmarkTools.Trial: 10000 samples with 999 evaluations.
 Range (min … max): 11.182 ns … 18.785 ns ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 12.085 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 12.035 ns ± 0.415 ns ┊ GC (mean ± σ): 0.00% ± 0.00%

  ▂▁ ▁ ▁▁ ▂▅ ▃▃ ▂▁ ▅██ ▇▆ ▂
  ██▃▄▁▁▁██▄███▃███▃██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▃▁▁▁▁▁▁▁▁▁▁▃██▄███▇███ █
  11.2 ns Histogram: log(frequency) by time 12.2 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

```

While calling it directly is much faster:

```julia
@benchmark ex_v_Vc1fDWJYMnSR(5)

```

```julia
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min … max): 0.020 ns … 0.031 ns ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 0.020 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 0.021 ns ± 0.003 ns ┊ GC (mean ± σ): 0.00% ± 0.00%

  █                                                          
  █▁▁▁▁▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▃ ▂
  0.02 ns Histogram: frequency by time 0.03 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

```

Complete and Unfinished… 🫠  
Help #performance #Performance

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [April 20, 2022, 8:15am UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/12 "2022-04-20T08:15:06Z")

</div>

The following code works for me

```julia
using BenchmarkTools
using Random

function create_ex_v_func(hook::Expr)
    new_func_name = Symbol("ex_v_" * randstring(12))

    eval(quote
        function $new_func_name(v_init::Integer)
            v = v_init
            x = 10
            y = 5
            z = 400
            $hook
            return z
        end
    end)

    return getfield(Main, new_func_name)
end

const hook1 = :(z += v + x*y)
const hook2 = :(z += v + x÷y)

const ex_v_f1 = create_ex_v_func(hook1)
const ex_v_f2 = create_ex_v_func(hook2)

@assert ex_v_f1(1) == (401 + 10*5)
@assert ex_v_f2(2) == (402 + 10÷5)

@benchmark ex_v_f1(5)

```

yielding

```julia
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min … max): 1.300 ns … 30.900 ns ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 1.300 ns ┊ GC (median): 0.00%        
 Time (mean ± σ): 1.346 ns ± 0.394 ns ┊ GC (mean ± σ): 0.00% ± 0.00%

  █                           
  █▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆ ▂
  1.3 ns Histogram: frequency by time 1.4 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

```

Edit: benchmarking with non const globals?

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [April 20, 2022, 8:15am UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/13 "2022-04-20T08:15:35Z")

</div>

Perhaps there are relevant insights to learn from the paper behind

> **[GitHub - MilesCranmer/SymbolicRegression.jl: Distributed High-Performance...](https://github.com/MilesCranmer/SymbolicRegression.jl)**
>
> Distributed High-Performance Symbolic Regression in Julia - GitHub - MilesCranmer/SymbolicRegression.jl: Distributed High-Performance Symbolic Regression in Julia

They are performing a similar search over functions to fit data.

> **[Discovering Symbolic Models from Deep Learning with Inductive Biases](https://arxiv.org/abs/2006.11287)**
>
> We develop a general approach to distill symbolic representations of a learned deep model by introducing strong inductive biases. We focus on Graph Neural Networks (GNNs). The technique works as follows: we first encourage sparse latent...

---

<div class="post-metadata">

**Author:** ![FireCrumb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/firecrumb/32/35370_2.png) [@FireCrumb](https://discourse.julialang.org/u/FireCrumb)\
**Post date:** [April 20, 2022, 9:21am UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/14 "2022-04-20T09:21:03Z")

</div>

> [@baggepinnen](#):
>
> Perhaps there are relevant insights to learn from the paper behind
> 
> [GitHub - MilesCranmer/SymbolicRegression.jl: Distributed High-Performance Symbolic Regression in Julia](https://github.com/MilesCranmer/SymbolicRegression.jl)
> 
> They are performing a similar search over functions to fit data.

Thanks for the great resource!  
It looks interesting, I’ll dive into it.

However, I’m building something more generic that can search for more unstructured code, so I want to be able to evaluate a dynamic function efficiently.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [April 20, 2022, 1:49pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/15 "2022-04-20T13:49:52Z")

</div>

> [@FireCrumb](#):
>
> ```julia
> BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
> Range (min … max): 0.010 ns … 0.031 ns ┊ GC (min … max): 0.00% … 0.00%
> Time (median): 0.020 ns ┊ GC (median): 0.00%
> Time (mean ± σ): 0.020 ns ± 0.002 ns ┊ GC (mean ± σ): 0.00% ± 0.00%
> 
> ▁ █ ▃ ▁ ▁
> █▁▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ █
> 0.01 ns Histogram: log(frequency) by time 0.03 ns <
> 
> ```

Those timings are fictitious and an effect of the compiler having constant folded the function and immediately returning the pre-computed result. Sanity check: look up your processor’s clock frequency and compute how many clock cycles it has time for in the reported time. If this seems unreasonably low compared to the computations you are doing, something is likely off with the benchmark.

> [@FireCrumb](#):
>
> But, wait!  
> I want to create many dynamic functions in runtime.
> 
> So, let’s create a random function name

You are probably better off just using anonymous functions.

> [@FireCrumb](#):
>
> There’s a big difference between the performance of calling the function directly by name, and invoking it through a pointer:

That’s an effect of using non-const globals and in particular that it inhibits the constant folding. This is maybe a better illustration (and also a demonstration of using anonymous functions):

```julia
julia> using BenchmarkTools

julia> f1 = x -> x^2
#1 (generic function with 1 method)

julia> const f2 = x -> x^2
#3 (generic function with 1 method)

julia> x = 5
5

julia> @btime f1($x)
  13.077 ns (0 allocations: 0 bytes)
25

julia> @btime f2($x)
  1.123 ns (0 allocations: 0 bytes)
25

```

---

<div class="post-metadata">

**Author:** ![FireCrumb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/firecrumb/32/35370_2.png) [@FireCrumb](https://discourse.julialang.org/u/FireCrumb)\
**Post date:** [April 20, 2022, 5:57pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/16 "2022-04-20T17:57:24Z")

</div>

Thanks @GunnarFarneback for the heads up about _constant folding_, I do realize that my example was so far from being realistic that the compiler optimized away relevant details.

Per my initial question, the goal of the injected code is to modify a variable in scope external to it.

So let’s look at this:

```julia
using BenchmarkTools

mutable struct state
    x::Int64
end

f1 = eval(
    quote
        state -> begin
            state.x = state.x + 1
        end
    end
)

const f2 = eval(
    quote
        state -> begin
            state.x = state.x + 1
        end
    end
)

```

And then the timing starts to look very similar:

```julia
s1 = state(0)
@btime f1(s1)
# 13.870 ns (1 allocation: 16 bytes)

s2 = state(0)
@btime f2(s2)
# 13.388 ns (1 allocation: 16 bytes)

```

---

<div class="post-metadata">

**Author:** ![FireCrumb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/firecrumb/32/35370_2.png) [@FireCrumb](https://discourse.julialang.org/u/FireCrumb)\
**Post date:** [April 20, 2022, 6:03pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/17 "2022-04-20T18:03:34Z")

</div>

However, I want to _search_ for candidate functions, so let’s just put the dynamic function creation into a loop, shall we?

```julia
using BenchmarkTools

mutable struct state
    x::Int64
end

function generate_candidate_func(param)::Function
    f = eval(
        quote
            state -> begin
                for t in 1:$param
                    state.x = state.x + 1
                end
            end
        end
    )
    return f
end

function search_candidate_func()
    desired_score = 50
    for i in 1:100
        candidate_func = generate_candidate_func(i)
        s = state(0)

        # ---> error here
        #
        # MethodError: no method matching (::var"#1#2")(::state)
        # The applicable method may be too new: running in world age 31336, while current world is 31337.
        # Closest candidates are:
        # (::var"#1#2")(::Any) at In[1]:10 (method too new to be called from this world context.)
        #
        candidate_func(s) # mutates s
        
        score = abs(desired_score - s.x)
        println(score)
    end
end

search_candidate_func()

```

**The applicable method may be too new?**  
Everything works fine when outside the _for loop_, so probably so magic parallel optimization happening behind the scenes… 😬

---

<div class="post-metadata">

**Author:** ![pfitzseb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pfitzseb/32/45566_2.png) [@pfitzseb](https://discourse.julialang.org/u/pfitzseb)\
**Post date:** [April 20, 2022, 6:13pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/18 "2022-04-20T18:13:22Z")

</div>

`Base.invokelatest` it.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [April 20, 2022, 6:18pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/19 "2022-04-20T18:18:40Z")

</div>

> [@FireCrumb](#):
>
> ```julia
> s2 = state(0)
> @btime f2(s2)
> # 13.388 ns (1 allocation: 16 bytes)
> 
> ```

That’s again a non-const global in your benchmark.

```julia
julia> const s3 = state(0)
state(0)

julia> @btime f2(s3);
  1.830 ns (0 allocations: 0 bytes)

```

or you can use BenchmarkTools interpolation feature to isolate your benchmark from that effect.

```julia
julia> @btime f2($s2);
  1.850 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [April 20, 2022, 6:23pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/20 "2022-04-20T18:23:18Z")

</div>

> [@FireCrumb](#):
>
> **The applicable method may be too new?**  
> Everything works fine when outside the _for loop_ , so probably so magic parallel optimization happening behind the scenes…

Time to revisit [Passing a string into function as a expression - #14 by GunnarFarneback](https://discourse.julialang.org/t/passing-a-string-into-function-as-a-expression/31625/14). Notice the call to `invokelatest`.

[Next page](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652.md?page=2)
