# Using @eval in a function

**URL:** https://discourse.julialang.org/t/using-eval-in-a-function/89488
**Category:** General Usage
**Tags:** macros, metaprogramming, eval, world\_age
**Created:** [October 29, 2022, 11:47am UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488 "2022-10-29T11:47:35Z")
**Posts on this page:** 18
**Page:** 1

<div class="post-metadata">

### Author: ![vitaminace33](https://avatars.discourse-cdn.com/v4/letter/v/9dc877/32.png) [@vitaminace33](https://discourse.julialang.org/u/vitaminace33)
#### Post date: [October 29, 2022, 11:47am UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/1 "2022-10-29T11:47:35Z")

</div>

Hi! I am trying to extend the methods of a collection of functions programmatically with no partial success.

```julia
foo(x::Real) = x
for f in (:foo,)
    @eval ($f)(x::Complex) = x'
end

function fun()
    foo(x::Real) = x
    for f in (:foo,)
        @eval ($f)(x::Complex) = x'
    end
    return foo
end
bar = fun()

methods(foo)

# 2 methods for generic function "foo":
[1] foo(x::Real) in Main at /home/cedricmc/Dropbox/Documentos/matematicas/articulos/2020-variational-accelerated-methods/simulations/test_eval.jl:1
[2] foo(x::Complex) in Main at /home/cedricmc/Dropbox/Documentos/matematicas/articulos/2020-variational-accelerated-methods/simulations/test_eval.jl:9

methods(bar)

# 1 method for generic function "foo":
[1] (::var"#foo#1")(x::Real) in Main at /home/cedricmc/Dropbox/Documentos/matematicas/articulos/2020-variational-accelerated-methods/simulations/test_eval.jl:7

```

I would expect that `foo` and `bar` have the same methods, however the complex method for `bar` is ignored. Why? I guess it is a scope problem. How to solve this so `bar` be like `foo`?

---

<div class="post-metadata">

### Author: ![vitaminace33](https://avatars.discourse-cdn.com/v4/letter/v/9dc877/32.png) [@vitaminace33](https://discourse.julialang.org/u/vitaminace33)
#### Post date: [October 29, 2022, 1:28pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/2 "2022-10-29T13:28:56Z")

</div>

I have updated the script with something more eloquent.

```julia
foo(x::Real) = x
f = :foo
eval("$f(x::Complex) = x'")
display(foo)
display(eval(f))

function fun()
    goo(x::Real) = x
    g = :goo
    eval("$g(x::Complex) = x'")
    display(goo)
    display(eval(g))
    return goo
end
bar = fun()

foo (generic function with 1 method)
foo (generic function with 1 method)
(::var"#goo#1") (generic function with 1 method)
ERROR: LoadError: UndefVarError: goo not defined

```

The first `eval` within `fun()` triggers no errors, but the second, `display(eval(g))`, does trigger an `UndefVarError`, which to me makes no sense.

---

<div class="post-metadata">

### Author: ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)
#### Post date: [October 29, 2022, 1:45pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/3 "2022-10-29T13:45:14Z")

</div>

> [@vitaminace33](#):
>
> ```julia
> function fun()
> goo(x::Real) = x
> g = :goo
> eval("$g(x::Complex) = x'")
> display(goo)
> display(eval(g))
> return goo
> end
> 
> ```

You’re returning a local variable `goo`. It’s not associated with the global symbol `:goo`. However, `eval` always runs in global scope and creates the only function associated with the global symbol `:goo`.

---

<div class="post-metadata">

### Author: ![vitaminace33](https://avatars.discourse-cdn.com/v4/letter/v/9dc877/32.png) [@vitaminace33](https://discourse.julialang.org/u/vitaminace33)
#### Post date: [October 29, 2022, 3:41pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/4 "2022-10-29T15:41:09Z")

</div>

> You’re returning a local variable `goo`.

Yes indeed

> It’s not associated with the global symbol `:goo`.

Why do you say “global”? There is no global symbol `:goo`.

> However, `eval` always runs in global scope and creates the only function associated with the global symbol `:goo`.

Had the first `eval` run in global scope, a function called `goo` in global scope should be defined for complex numbers, however no function `goo` is created in global (or local) scope, hence the error of the second `display`.

Using quoting, `eval(:($g(x::Complex) = x'))`, or macro, `@eval $g(x::Complex) = x'`, behaves as you say.

---

<div class="post-metadata">

### Author: ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)
#### Post date: [October 29, 2022, 3:45pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/5 "2022-10-29T15:45:46Z")

</div>

I think you’re dealing with a “world age” issue.

> [@World Age Problem Explanation](https://discourse.julialang.org/t/world-age-problem-explanation/9714):
>
> Hello. Recently I have faced the “world age problem” several times. That means, after searching for my problems, this website came up with themes like “world age workaround” or “How to Bypass the World Age Problem”. I am not a computer scientist, so maybe this is a stupid question, but I have not found a explanation of this problem; where can I get information what actually happens there? Or, more clearly, what is the “World Age Problem”? As you can imagine, if I google this, I get a lot of i…

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [October 29, 2022, 6:58pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/6 "2022-10-29T18:58:03Z")

</div>

> [@vitaminace33](#):
>
> Had the first `eval` run in global scope, a function called `goo` in global scope should be defined for complex numbers

Every `eval` runs in global scope, and eval’ing a string does not define a function, it merely evals the string. Your first example, with the `foo` functions suffers from this. A slight variation shows what happens:

```julia
foo(x::Real) = x
for f in (:foo,)
    @eval ($f)(x::Complex) = x'
end

function fun()
    foo(x::Real) = x
    for f in (:foo,)
        @eval ($f)(x::Rational) = x'
    end
    return foo
end
bar = fun()

methods(foo)

```

yields

> (::var"#foo#5") (generic function with 1 method)  
> # 3 methods for generic function “foo” from Main:  
> [1] foo(x::Complex)  
> @ REPL[2]:2  
> [2] foo(x::Rational)  
> @ REPL[3]:4  
> [3] foo(x::Real)  
> @ REPL[1]:1

This shows that the `eval` inside a function runs in global scope, and does not add methods to the local function `foo`.

---

<div class="post-metadata">

### Author: ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)
#### Post date: [October 29, 2022, 7:47pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/7 "2022-10-29T19:47:42Z")

</div>

> [@sgaure](#):
>
> eval’ing a string does not define a function, it merely evals the string.

Right! I was on my phone and didn’t notice that earlier. Eval operates on expressions. You’d need to parse it first!

---

<div class="post-metadata">

### Author: ![vitaminace33](https://avatars.discourse-cdn.com/v4/letter/v/9dc877/32.png) [@vitaminace33](https://discourse.julialang.org/u/vitaminace33)
#### Post date: [October 29, 2022, 8:16pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/8 "2022-10-29T20:16:04Z")

</div>

> [@sgaure](#):
>
> eval’ing a string does not define a function, it merely evals the string

I did not know/understand this, thx.

> [@sgaure](#):
>
> A slight variation shows what happens:

It is similar to my second example but more clarifying, thx again.

Coming back to my initial post, how can I create a function within a function, specify it programmatically and return it?

```julia
function fun()
    foo(x::Real) = x
    f = :foo
    @eval $f(x::Complex) = x'
    return foo
end
bar = fun()
varinfo()

  name size summary                                         
  –––––––––––––––– ––––––––––– ––––––––––––––––––––––––––––––––––––––––––––––––
  Base Module                                          
  Core Module                                          
  InteractiveUtils 307.688 KiB Module                                          
  Main Module                                          
  bar 0 bytes (::var"#foo#1") (generic function with 1 method)
  foo 0 bytes foo (generic function with 1 method)            
  fun 0 bytes fun (generic function with 1 method) 

```

I would like `bar` to have two methods, the ones that currently have `foo` and `bar` itself.

---

<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: [October 29, 2022, 8:41pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/9 "2022-10-29T20:41:20Z")

</div>

I’m not sure if you are mixing different concepts here. The following seems to work for me

```julia
fun_returning() = x::Real -> x
proc_evaluating() = @eval foo(x::Complex) = x
bar = fun_returning()
@show bar(42.0)
proc_evaluating()
@show foo(Complex(42.0, 43.0))

```

yielding

```julia
bar(42.0) = 42.0
foo(Complex(42.0, 43.0)) = 42.0 + 43.0im

```

(and this is not yet a problem of world age, which I suspected, too).

---

<div class="post-metadata">

### Author: ![vitaminace33](https://avatars.discourse-cdn.com/v4/letter/v/9dc877/32.png) [@vitaminace33](https://discourse.julialang.org/u/vitaminace33)
#### Post date: [October 29, 2022, 8:51pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/10 "2022-10-29T20:51:37Z")

</div>

Thx but this is not what I need.

> [@vitaminace33](#):
>
> I would like `bar` to have **two** methods, the ones that currently have `foo` and `bar` itself.

[Documentation](https://docs.julialang.org/en/v1/manual/methods/#Redefining-Methods) refers to this and it seems to be world age realated.

---

<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: [October 29, 2022, 8:57pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/11 "2022-10-29T20:57:19Z")

</div>

OK, let us try

```julia
test() = begin
    @eval foo(x::Real) = x
    @eval foo(x::Complex) = x
end
test()
varinfo()

```

yielding

```julia
  name size summary
  –––––––––––––––– ––––––––––– –––––––––––––––––––––––––––––––––––––
  Base Module
  Core Module
  InteractiveUtils 331.024 KiB Module
  Main Module
  foo 0 bytes foo (generic function with 2 methods)
  test 0 bytes test (generic function with 1 method)

```

then.

---

<div class="post-metadata">

### Author: ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)
#### Post date: [October 29, 2022, 9:18pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/12 "2022-10-29T21:18:10Z")

</div>

within a single function call, using `@eval` to create a new method and then trying to immediately call that method will I think not work, because of world age.

---

<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: [October 29, 2022, 9:21pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/13 "2022-10-29T21:21:59Z")

</div>

Yes, that was what I thought, but:

```julia
test() = begin
    @eval foo(x::Real) = x
    @eval foo(x::Complex) = x
end
test()
@show foo(42.0)
@show foo(Complex(42.0, 43.0))
versioninfo()

```

yields

```julia
foo(42.0) = 42.0
foo(Complex(42.0, 43.0)) = 42.0 + 43.0im
Julia Version 1.8.2
Commit 36034abf26 (2022-09-29 15:21 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: 12 × Intel(R) Core(TM) i7-10710U CPU @ 1.10GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, skylake)
  Threads: 4 on 12 virtual cores
Environment:
  JULIA_EDITOR = code
  JULIA_NUM_THREADS = 4

```

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [October 29, 2022, 9:24pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/14 "2022-10-29T21:24:13Z")

</div>

You can generate an “anonymous” name with gensym() and define various methods with eval:

```julia

function fun(x)
    nm = gensym()
    T = widen(Complex{Float32})
    y = x^2
    @eval begin
        $nm(x::Real) = x
        $nm(x::$T) = x' + $y
    end
end

bar = fun(2.0)

methods(bar)

bar(1)
bar(1.0+im)

```

yields the output

> ##295 (generic function with 2 methods)  
> # 2 methods for generic function “##295” from Main:  
> [1] var"##295"(x::Real)  
> @ REPL[9]:6  
> [2] var"##295"(x::ComplexF64)  
> @ REPL[9]:7  
> 1  
> 5.0 - 1.0im

But take note of the “world age” problem that was referenced above, new methods/functions are not immediately visible.

---

<div class="post-metadata">

### Author: ![vitaminace33](https://avatars.discourse-cdn.com/v4/letter/v/9dc877/32.png) [@vitaminace33](https://discourse.julialang.org/u/vitaminace33)
#### Post date: [October 29, 2022, 9:30pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/15 "2022-10-29T21:30:48Z")

</div>

> [@goerch](#):
>
> ```julia
> test() = begin
> @eval foo(x::Real) = x
> @eval foo(x::Complex) = x
> end
> 
> ```

Nice approach, but the first `foo` could overwrite an existing method.

> [@sgaure](#):
>
> `nm = gensym()`

This might be key. I’m gonna give it a try.

---

<div class="post-metadata">

### Author: ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)
#### Post date: [October 29, 2022, 9:49pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/16 "2022-10-29T21:49:17Z")

</div>

> [@goerch](#):
>
> Yes, that was what I thought, but:

by “immediate” i mean within the same function call where it was defined.

```julia
julia> test() = begin
           @eval foo(x::Real) = x
           @eval foo(x::Complex) = x
           foo(1+1im) # will error
       end
test (generic function with 1 method)

julia> test()
ERROR: MethodError: no method matching foo(::Complex{Int64})
The applicable method may be too new: running in world age 32433, while current world is 32435.
Closest candidates are:
  foo(::Complex) at REPL[1]:3 (method too new to be called from this world context.)
  foo(::Real) at REPL[1]:2 (method too new to be called from this world context.)
Stacktrace:
 [1] test()
   @ Main ./REPL[1]:4
 [2] top-level scope
   @ REPL[2]:1

```

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [October 29, 2022, 9:57pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/17 "2022-10-29T21:57:13Z")

</div>

> [@vitaminace33](#):
>
> > [@sgaure](#):
> >
> > `nm = gensym()`
> 
> This might be key. I’m gonna give it a try.

You may make it even more anonymous:

```julia
function fun(x)
    T = widen(Complex{Float32})
    y = x^2
    @eval let foo = x::Real -> x
        (::typeof(foo))(x::$T) = x' + $y
        foo
    end
end

bar = foo(2.0)

```

However, the only difference I’ve noticed is that the output of `methods(bar)` states that it is an anonymous function, not a generic function. I don’t know the difference.

---

<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: [October 29, 2022, 10:40pm UTC](https://discourse.julialang.org/t/using-eval-in-a-function/89488/18 "2022-10-29T22:40:23Z")

</div>

> [@vitaminace33](#):
>
> Hi! I am trying to extend the methods of a collection of functions programmatically with no partial success.

Can you step back and tell us what you are trying to accomplish? Trying to `@eval` in a function is usually an indication that you made a wrong turn somewhere.

The usual way to create new functions inside a function (i.e. a higher-order function) is to return a closure (an anonymous function), not to do code generation / metaprogramming.
