# Eval a string with runtime defined functions

**URL:** <https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290>\
**Category:** General Usage\
**Created:** [March 7, 2024, 12:32pm UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290 "2024-03-07T12:32:07Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![phyxmeow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phyxmeow/32/36373_2.png) [@phyxmeow](https://discourse.julialang.org/u/phyxmeow)\
**Post date:** [March 7, 2024, 12:32pm UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/1 "2024-03-07T12:32:07Z")

</div>

Hello, how to make this work? And if possible, work performantly.

```julia
julia> function foo(str, n)
           f(x) = x+n
           eval(Meta.parse(str))
       end
foo (generic function with 2 methods)

julia> foo("f(1)", 5)
ERROR: UndefVarError: `f` not defined
Stacktrace:
 [1] top-level scope
   @ none:1
 [2] eval
   @ ./boot.jl:385 [inlined]
 [3] eval
   @ ./client.jl:491 [inlined]
 [4] foo(str::String, n::Int64)
   @ Main ./REPL[6]:3
 [5] top-level scope
   @ REPL[7]:1

```

---

<div class="post-metadata">

**Author:** ![phyxmeow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phyxmeow/32/36373_2.png) [@phyxmeow](https://discourse.julialang.org/u/phyxmeow)\
**Post date:** [March 7, 2024, 12:41pm UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/2 "2024-03-07T12:41:55Z")

</div>

```julia
julia> function foo(str, n)
           expr = Meta.parse(str)
           eval(quote f(x)=x+$n; $expr end)
       end
foo (generic function with 2 methods)

julia> foo("f(1)", 5)
6

julia> f(1)
6

```

I find this works, but the function `f` is defined to global scope, which is not good.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [March 7, 2024, 12:49pm UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/3 "2024-03-07T12:49:41Z")

</div>

Generally speaking, you don’t. We recommend very strongly against string-based metaprogramming here. There is usually a better, different way to accomplish these sorts of goals, but we’d need to know your actual usecase to give clearer advice than that.

`eval` always operates in the global scope, and most of julia’s performance optimizations would not be possible if it was able to access the local scope.

---

<div class="post-metadata">

**Author:** ![phyxmeow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phyxmeow/32/36373_2.png) [@phyxmeow](https://discourse.julialang.org/u/phyxmeow)\
**Post date:** [March 7, 2024, 12:54pm UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/4 "2024-03-07T12:54:51Z")

</div>

Hello, thank you for your advice. I’m writing an application that need to parse some math expressions from user input. Which involve a custom function, say `foo(x)`, whose behavior is context dependent. I want to reuse julia’s parser so that I need not to write one myself.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [March 7, 2024, 1:18pm UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/5 "2024-03-07T13:18:33Z")

</div>

If you’re using Julia’s parser, then the user inputs must be Julia expressions. Why not distribute these custom functions in a package to the users so they can import it and execute the math expressions in a REPL, or even use it to write their own scripts?

---

<div class="post-metadata">

**Author:** ![mnemnion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mnemnion/32/206596_2.png) [@mnemnion](https://discourse.julialang.org/u/mnemnion)\
**Post date:** [March 8, 2024, 2:12am UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/6 "2024-03-08T02:12:41Z")

</div>

> [@Mason](#):
>
> `eval` always operates in the global scope, and most of julia’s performance optimizations would not be possible if it was able to access the local scope.

I’d be interested in hearing more about why that is. I would have thought given this:

```julia
julia> shmeval = eval
eval (generic function with 1 method)

julia> shmeval
eval (generic function with 1 method)

```

That the compiler doesn’t have to harbor the suspicion that any old function call might be eval in disguise. It knows eval. Why would allowing use of eval in local scope disturb performance optimizations in local scopes where it isn’t invoked?

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [March 8, 2024, 2:34am UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/7 "2024-03-08T02:34:29Z")

</div>

The problem with `eval` is that it changes the definition of what an arbitrary function does at the time it is called. Pretty much every optimization a compiler does involves being able to change the time when an operation happens. If you have a local eval in the language, you need to be able to prove that a function never calls `eval` anywhere in it’s call graph in order to be able to optimize anything about the function.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [March 8, 2024, 3:42am UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/8 "2024-03-08T03:42:36Z")

</div>

On a lower level, the native code completely lacks any concept of Julia variables and manipulates offsets in a stack frame or addresses on the heap. An `eval` call inside a local scope actually working within that local scope like the rest of the code would require jumps to arbitrary instructions and a very dynamically sized stack frame. You would have to retain the concept of variables at that level, like storing a dictionary of symbols to values. Type inference would be impossible, in other words the local variables can only be inferred as `::Any` when compiling the method:.

```julia
function foo(string::String)
  a = 1
  localeval(string)
  a
end

foo("a = 1im; a = 2.5; a = false") # local a is not just Int

```

Besides preventing almost every compiler optimization, it’s also a nightmare to work with. `foo("a + b")` would throw an undefined variable error, and nobody wants to track down method bodies to figure out the local scope. Even the less optimized dynamic languages don’t do this.

---

<div class="post-metadata">

**Author:** ![mnemnion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mnemnion/32/206596_2.png) [@mnemnion](https://discourse.julialang.org/u/mnemnion)\
**Post date:** [March 8, 2024, 3:50am UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/9 "2024-03-08T03:50:40Z")

</div>

> [@Oscar\_Smith](#):
>
> The problem with `eval` is that it changes the definition of what an arbitrary function does at the time it is called. Pretty much every optimization a compiler does involves being able to change the time when an operation happens.

Ok, I’m with you so far. Something like

```julia
function slow_fn(a,to_eval)
     x = 5
     y = local_eval(to_eval)
     x *= a
     return return x + y
end

```

This function can do anything to `x` or `a`, nothing can be assumed about `y`, it’s pessimal.

> [@Oscar\_Smith](#):
>
> If you have a local eval in the language, you need to be able to prove that a function never calls `eval` anywhere in it’s call graph in order to be able to optimize anything about the function.

This is what I don’t get.

```julia
function deep_eval_call(a...)
    acc = Any[]
    push!(acc, slow_fn(acc[end], "code goes here")
    for i in 1:10000
         push!(acc, optimizable(i, a...))
    end
    acc
end

```

I’m not seeing how the eval call in `slow_fn`, which can only affect the lexical scope it’s defined in, can affect optimizing the code in the rest of the scope. That’s not a disagreement, I just don’t get it yet: it looks like an ordinary type-unstable function call, and those don’t cascade around breaking things.

---

<div class="post-metadata">

**Author:** ![phyxmeow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phyxmeow/32/36373_2.png) [@phyxmeow](https://discourse.julialang.org/u/phyxmeow)\
**Post date:** [March 8, 2024, 3:53am UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/10 "2024-03-08T03:53:19Z")

</div>

Okey, I come to a solution that to write a eval function that gives result of an expr myself. I realized I want to reuse the parser not the eval function. Then I can completely customize the function behavior.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [March 8, 2024, 4:10am UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/11 "2024-03-08T04:10:57Z")

</div>

The problem is that the lexical scope `slow_fn` is defined in can include the global scope. For a dramatic example, consider

```julia
badfun() = local_eval("Base.(+)(a::Int, b::Int) = 1")

function f(x)
    badfun()
    return x + 1
end
f(2)

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [March 8, 2024, 4:40am UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/12 "2024-03-08T04:40:38Z")

</div>

> [@phyxmeow](#):
>
> I come to a solution that to write a eval function that gives result of an expr myself. I realized I want to reuse the parser not the eval function. Then I can completely customize the function behavior.

What are you doing here exactly? How would a different eval function help?

> [@Oscar\_Smith](#):
>
> The problem is that the lexical scope `slow_fn` is defined in can include the global scope.

But if `local_eval` somehow disallows undesired effects on the global scope, then it seems right that the only bad effects that `slow_fn` has on `deep_eval_call` in mnemnion’s example is the poor return type inference, and the rest of `deep_eval_call` can be optimized normally. “Undesired global effects” doesn’t seem easy to delineate, and it doesn’t seem worth working with that limitation just to compile the least performant caller methods.

---

<div class="post-metadata">

**Author:** ![phyxmeow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phyxmeow/32/36373_2.png) [@phyxmeow](https://discourse.julialang.org/u/phyxmeow)\
**Post date:** [March 8, 2024, 5:13am UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/13 "2024-03-08T05:13:26Z")

</div>

Sorry for not speak clearly. The user input string may contains a custom operator, lets call it ⊗. I need to calculate the value of the expression, but with a runtime generated parameter passed to all function call of ⊗. So once I get the expr, I can walk and calculate it top to bottom, and insert the parameter when I meet operator ⊗.

Edit: I have a even better idea. Let me write this:

```julia
function new_param()
    data = 1
    get() = data
    set!(val) = (data = val)
    return (get, set!)
end

get_param, set_param! = new_param()

⊗(a, b; param = get_param()) = ...

function main()
    # Do something
    set_param!(some_value)
    eval(user_str)
end

```

This new method introduces some global state, I guess it may not be safe when doing async work?

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [March 8, 2024, 7:26am UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/14 "2024-03-08T07:26:58Z")

</div>

> [@phyxmeow](#):
>
> So once I get the expr, I can walk and calculate it top to bottom, and insert the parameter when I meet operator ⊗.

If you just want the expression, you could maybe just use `Meta.parse` to convert the string to an `Expr`?

```julia-repl
julia> Meta.parse("x + 5 ⊗ 3")
:(x + 5 ⊗ 3)

julia> dump(ans)
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol +
    2: Symbol x
    3: Expr
      head: Symbol call
      args: Array{Any}((3,))
        1: Symbol ⊗
        2: Int64 5
        3: Int64 3

```

Edit: To expand a bit on this: When you walk that expression tree, for every function call you can just check the symbol in `args[1]`. If it is your special symbol, you call whatever it should do and else it should be one of Julia’s functions which you can get the function object of via `getfield(Main, symbol)`.

---

<div class="post-metadata">

**Author:** ![phyxmeow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phyxmeow/32/36373_2.png) [@phyxmeow](https://discourse.julialang.org/u/phyxmeow)\
**Post date:** [March 8, 2024, 7:30am UTC](https://discourse.julialang.org/t/eval-a-string-with-runtime-defined-functions/111290/15 "2024-03-08T07:30:50Z")

</div>

Yes, actually I did exactly as what you say. No problem anymore.
