# Trouble with @eval with mixed variable scopes

**URL:** <https://discourse.julialang.org/t/trouble-with-eval-with-mixed-variable-scopes/34483>\
**Category:** General Usage\
**Created:** [February 11, 2020, 7:04pm UTC](https://discourse.julialang.org/t/trouble-with-eval-with-mixed-variable-scopes/34483 "2020-02-11T19:04:28Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![arik](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@arik](https://discourse.julialang.org/u/arik)\
**Post date:** [February 11, 2020, 7:04pm UTC](https://discourse.julialang.org/t/trouble-with-eval-with-mixed-variable-scopes/34483/1 "2020-02-11T19:04:28Z")

</div>

Hi there. I have found some behavior of the “@eval”-macro that I cant quite explain.  
So, as far as I understand it, “@eval expr” takes a segment of code, and evaluates it as if it had been written at that point in the sourcecode. But if “expr” mixes the global variable-scope with a local one, it seems to not work properly.  
An example:

```julia
@eval begin
    x=1;
    x+=1
    println(x)
end
println("this worked!")
```

This returns

> 2  
> this worked!

, as is expected. But if I write

```julia
@eval begin
    x=1;
    while x<2
        x+=1
    end
    println(x)
end
println("This did not work!")
```

, then I get

> UndefVarError: x not defined  
> Stacktrace:  
> [1] top-level scope at .\In[2]:4  
> [2] eval(::Module, ::Any) at .\boot.jl:330

It seems that the x in ` x+=1 ` in the scope of the while-loop is no longer recognized. The same happens with a for-loop instead of “while”.  
If I just remove the “@eval” it works of course as intended  
I can also fix this by encapsulating the x in its own scope:

```julia
@eval begin
    let x=1
        while x<2
            x+=1
        end
        println(x)
    end
end
println("This works again!")
```

this, again, results in

> 2  
> This works again!

As I see it, all three versions should return 2. Of course I can work around this, but I would like to know whether this is a bug, or, if not, why this happens.

Notes:  
-I tried this with versions 1.2.0 and 1.3.1, in both a shell and a notebook, with identical results.

-this is not a purely artifical problem, but a reduced form of an error with my Script for data-evaluation. When I `include(...)` that Script I run into exactly the same error, and `include` - as i understand it - uses the eval-function on whatever is provided as an argument.

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [February 11, 2020, 7:48pm UTC](https://discourse.julialang.org/t/trouble-with-eval-with-mixed-variable-scopes/34483/2 "2020-02-11T19:48:55Z")

</div>

`@eval` works in global scope. A `while` loop introduces a local scope, in which global variables cannot be changed unless you use `global`:

```julia
julia> begin
    x=1;
    while x<2
        global x+=1
    end
    println(x)
end
2
julia> x
2

```

`let` introduces a local scope. Inside a local scope variables can be modified within `for` or `while`. Therefore your 3rd example works. But, if you restart the repl and do

```julia
julia> begin
    let x=1
        while x<2
            x+=1
        end
        println(x)
    end
end
2
julia> x
ERROR: UndefVarError: x not defined

```

See the [Julia manual](https://docs.julialang.org/en/v1/manual/variables-and-scoping/#Local-Scope-1) on this.

---

<div class="post-metadata">

**Author:** ![arik](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@arik](https://discourse.julialang.org/u/arik)\
**Post date:** [February 12, 2020, 10:37am UTC](https://discourse.julialang.org/t/trouble-with-eval-with-mixed-variable-scopes/34483/3 "2020-02-12T10:37:34Z")

</div>

I understand local and global scopes, thats not the point. My question concerns the behavior of the macro. Evaluating either of my three code-snippets (in a global scope) _should_ yield the same result with or without the macro (deleting the @eval should not change anything). This holds for example 1 and 3 (without loop and with wrapped loop). But the second example (the unwrapped while-loop) breaks if evaluated with the macro, and works just fine without it.

---

<div class="post-metadata">

**Author:** ![thofma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thofma/32/1691_2.png) [@thofma](https://discourse.julialang.org/u/thofma)\
**Post date:** [February 12, 2020, 10:48am UTC](https://discourse.julialang.org/t/trouble-with-eval-with-mixed-variable-scopes/34483/4 "2020-02-12T10:48:26Z")

</div>

No, your second example does not work without the `@eval`:

```julia
julia> begin
           x=1;
           while x<2
               x+=1
           end
           println(x)
       end
       println("This did not work!")
ERROR: UndefVarError: x not defined
Stacktrace:
 [1] top-level scope at ./REPL[2]:4

```

I tried it on `1.1` and `1.2`.

---

<div class="post-metadata">

**Author:** ![arik](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@arik](https://discourse.julialang.org/u/arik)\
**Post date:** [February 12, 2020, 11:27am UTC](https://discourse.julialang.org/t/trouble-with-eval-with-mixed-variable-scopes/34483/5 "2020-02-12T11:27:34Z")

</div>

Interesting…  
I usually work in Jupyter Lab.

I’ve tried exacly this code in a fresh jupyter notebook, and it works (returns 2, no error)! I tried the same in the jupyter console, and it still works! I tried it in an ordinary julia console, and now exactly the same code breaks (UndefVarError, as in your example)!  
So it seems this arises from the way that jupyter handles its scopes?

(Btw could someone point me to a tutorial on how to include these console-commands+output? Im new here and have not figured this out yet)

 ![jupyterConsole](https://global.discourse-cdn.com/julialang/original/3X/f/8/f86a5879c9aff13defe51a55797c2d251149b860.png)

---

<div class="post-metadata">

**Author:** ![thofma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thofma/32/1691_2.png) [@thofma](https://discourse.julialang.org/u/thofma)\
**Post date:** [February 12, 2020, 11:34am UTC](https://discourse.julialang.org/t/trouble-with-eval-with-mixed-variable-scopes/34483/6 "2020-02-12T11:34:23Z")

</div>

I am not too familiar with Jupyter, but I think it changes the scope behaviour by default (see [GitHub - JuliaLang/IJulia.jl: Julia kernel for Jupyter](https://github.com/JuliaLang/IJulia.jl#opting-out-of-soft-scope)). There it is also explained how to get the raw REPL scope experience 🙂

Regarding the code blocks have a look at [Please read: make it easier to help you](https://discourse.julialang.org/t/psa-make-it-easier-to-help-you/14757).

---

<div class="post-metadata">

**Author:** ![arik](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@arik](https://discourse.julialang.org/u/arik)\
**Post date:** [February 12, 2020, 11:52am UTC](https://discourse.julialang.org/t/trouble-with-eval-with-mixed-variable-scopes/34483/7 "2020-02-12T11:52:30Z")

</div>

@thofma  
👍 Ty, I was not aware of that “softscope”-thing. This explains it though. Since I had trouble before with accidental mixing of scopes I think I will opt out of this in the future.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [February 12, 2020, 5:17pm UTC](https://discourse.julialang.org/t/trouble-with-eval-with-mixed-variable-scopes/34483/8 "2020-02-12T17:17:52Z")

</div>

For what it’s worth, in Julia 1.5 the REPL will behave the same way as IJulia currently does (aka soft scope), while in non-interactive contexts (files, eval) there will be a warning telling you that you need to disambiguate the inner `x` by explicitly declaring it as `local` or `global`.
