# 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:** 3\
**Page:** 2

<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:24pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/21 "2022-04-20T18:24:36Z")

</div>

> [@pfitzseb](#):
>
> `Base.invokelatest` it.

Thanks! It works when using `invokelatest`.  
Why is it actually needed in this case? What isn’t “latest” when I create functions in the loop?

How will it behave in a multi-threaded environment when the code inside the loop is done by different workers? Will they have a collision?

---

<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, 6:33pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/22 "2022-04-20T18:33:00Z")

</div>

> [@FireCrumb](#):
>
> Why is it actually needed in this case? What isn’t “latest” when I create functions in the loop?

`eval` changes world age, which is needed to keep coherence when redefining functions which are already referenced by other functions.

---

<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, 7:25pm UTC](https://discourse.julialang.org/t/pass-expression-to-manipulate-local-variable/79652/23 "2022-04-20T19:25:54Z")

</div>

I think I’ve finally got it, thanks to everyone in this thread for the help!!! 😃

Here’s the code after it _evolved_ (hehe) through this thread:

```julia
mutable struct state
    x::Int64
end

generate_candidate_func(hook) = eval(
    quote
        state -> begin
            for t in 1:1000
                $hook
            end
        end
    end
)

function eval_candidate_func(hook::Expr, invoke_times=1)
    candidate_func = generate_candidate_func(hook)
    
    sx_max = 0
    for i in 1:invoke_times
        s = state(0)
        Base.invokelatest(candidate_func, s) # mutates s
        sx_max = max(s.x, sx_max)
    end

    return sx_max
end

function search_candidate_func(n_iter)
    desired_score = 50
    best_score = Inf
    for i in 1:n_iter
        hook = :(state.x = $i)
        sx = eval_candidate_func(hook)
        score = min(best_score, abs(desired_score - s.x))
    end
    best_score
end

```

The compilation takes short time, and the execution of the compiled function takes negligible time:

```julia
myhook = :(state.x = 50)
eval_candidate_func(myhook, 1) # warm up hook before benchmark

@btime eval_candidate_func($myhook, 1)
# 3.202 ms (17874 allocations: 1.08 MiB)

@btime eval_candidate_func($myhook, 100)
# 3.220 ms (17973 allocations: 1.08 MiB)

@btime eval_candidate_func($myhook, 1000)
# 3.387 ms (18873 allocations: 1.09 MiB)

```

* * *

So to answer directly to my simple example from the original question

> [@FireCrumb](#):
>
> 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
> 
> ```

A working solution for my wrongly phrased question would be:

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

@assert ex_v(0, :(v = v+1)) == 1

```

But the solution which I _actually_ needed would be:

```julia
function ex_v_func(hook::Expr)
    eval(
        quote
            v_init::Integer -> begin
                v = v_init
                $hook
                return v
            end
        end
    )
end

ex_v = ex_v_func(:(v = v+1))
@assert ex_v(0)==1

```

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