# Variable scope concept

**URL:** <https://discourse.julialang.org/t/variable-scope-concept/122277>\
**Category:** General Usage\
**Tags:** scope\
**Created:** [November 5, 2024, 9:53am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277 "2024-11-05T09:53:52Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![hack3rcon](https://avatars.discourse-cdn.com/v4/letter/h/96bed5/32.png) [@hack3rcon](https://discourse.julialang.org/u/hack3rcon)\
**Post date:** [November 5, 2024, 9:53am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/1 "2024-11-05T09:53:52Z")

</div>

Hello,  
Why is the error related to the variable scope given in the following code?

```julia
num = 0
for line in eachline("file.txt")
    num +=1
end
print(num)

```

The error is:

```julia
┌ Warning: Assignment to `num` in soft scope is ambiguous because a global variable by the same name exists: `num` will be treated as a new local. Disambiguate by using `local num` to suppress this warning or `global num` to assign to the existing global variable.
└ @ ~/Downloads/Julia/File.jl:169
ERROR: LoadError: UndefVarError: `num` not defined

```

Thank you.

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [November 5, 2024, 10:22am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/2 "2024-11-05T10:22:05Z")

</div>

There’s a manual section on scope, but I think the most helpful suggestion is actually to put code like this within a function.

I will again note that this could be re-written as a one-liner 😛

```julia
julia> count(Returns(true), eachline("file.txt"))
293

```

---

<div class="post-metadata">

**Author:** ![hack3rcon](https://avatars.discourse-cdn.com/v4/letter/h/96bed5/32.png) [@hack3rcon](https://discourse.julialang.org/u/hack3rcon)\
**Post date:** [November 5, 2024, 10:31am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/3 "2024-11-05T10:31:58Z")

</div>

Hello,  
Thank you so much for your advice.  
I am a newbie and I want to know where my problem is and to better understand the concept of Julia programming language.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [November 5, 2024, 10:36am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/4 "2024-11-05T10:36:32Z")

</div>

This is my explanation of that: [Scope of loops · JuliaNotes.jl](https://m3g.github.io/JuliaNotes.jl/v1.1/loopscopes/)

It is likely superficial and imprecise, but I think easier to understand than what’s in the manual.

---

<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:** [November 5, 2024, 10:47am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/5 "2024-11-05T10:47:01Z")

</div>

As you probably have tried, it works in the interactive REPL and notebooks, but not in files or in Julia expressions. Yes this is a very weird discrepancy with a weird history, it’s intuitive to nobody.

> **Minimal example in the REPL**
>
> ```julia
> julia> x = 0
> 0
> 
> julia> for i in 1:10
> x += i
> end
> 
> julia> x
> 55
> 
> julia> @eval begin
> x = 0
> for i in 1:10
> x += i
> end
> x
> end
> ┌ Warning: Assignment to `x` in soft scope is ambiguous because a global variable by the same name exists: `x` will be treated as a new local. Disambiguate by using `local x` to suppress this warning or `global x` to assign to the existing global variable.
> └ @ REPL[4]:4
> ERROR: UndefVarError: `x` not defined in local scope
> 
> ```

First the principles. You need to declare global variables, like `global num` in another (even subsequent!) line or `global num += 1` in the same line, in local scopes. All blocks except `begin` and `if` introduce a local scope for convenient variable lifetimes and capturing, so you’ll have to write `global` often if you work with global variables. Alternatively, you could put the whole thing in a `let` block so it’s all local variables.

The reason for a local scope freely borrowing from outer local scopes but not the global scope is because only the global scope can be scattered across several `include`-d files, so this disambiguation protects you from accidentally reassigning a global variable from 15 files ago when you meant to write a local variable. The soft scope concept relaxes this for `for`, `while`, `try`, and `struct` blocks for convenient use in the REPL and notebooks, especially pasting local scope code. (I’m actually not sure why `struct` was included because `struct` blocks don’t run code outside its inner constructors in practice.)

> **Described fixes for the minimal example earlier**
>
> ```julia
> julia> @eval begin
> x = 0
> for i in 1:10
> global x += i
> end
> x
> end
> 55
> 
> julia> @eval let
> x = 0
> for i in 1:10
> x += i
> end
> x
> end
> 55
> 
> ```

Now the history. The relaxed behavior was around first, but people complained it was hard to remember and tell which blocks would make an assignment affect a global variable, especially from another file. So, the stricter behavior was done for all local scope blocks in v1.

Then people complained they needed to write `global` everywhere and remove it for pasting into local scopes. While some new users from other languages were just complaining this isn’t what they’re used to, there was an annoying factor that affected anyone: executing code by line is routinely done for debugging and development, and running lines in the globally scoped REPL had to be done when the debuggers that could step through local scopes weren’t around yet. IJulia (for Jupyter) independently reverted to the pre-v1 behavior, so v1.5 introduced the soft scope concept as a compromise to divide the relaxed and strict behaviors for where they were demanded the most.

I personally dislike this discrepancy and would prefer the strict v1 behavior for safety, but since v1 had to exist first for debuggers to even start development, I don’t know how it should have turned out differently. I also definitely wouldn’t want more blocks to not introduce local scopes; that’s a few more major gripes in other languages I’m glad to not to deal with.

---

<div class="post-metadata">

**Author:** ![hack3rcon](https://avatars.discourse-cdn.com/v4/letter/h/96bed5/32.png) [@hack3rcon](https://discourse.julialang.org/u/hack3rcon)\
**Post date:** [November 5, 2024, 10:48am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/6 "2024-11-05T10:48:28Z")

</div>

Hello,  
Thank you so much.  
Your example is similar to what I have done:

```julia
s = 0
for i in 1:3
    s = s + i
end

```

It works for you, but not for me. I use **VSCodium**. I ran the same code using the julia command and it worked!  
Why?

---

<div class="post-metadata">

**Author:** ![hack3rcon](https://avatars.discourse-cdn.com/v4/letter/h/96bed5/32.png) [@hack3rcon](https://discourse.julialang.org/u/hack3rcon)\
**Post date:** [November 5, 2024, 10:54am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/7 "2024-11-05T10:54:38Z")

</div>

Hello,  
Thanks.  
I tested two types of code:

```julia
global num = 0
for line in eachline("file.txt")
   num +=1
end
print(num)

```

And:

```julia
num = 0
for line in eachline("file.txt")
   global num +=1
end
print(num)

```

Why does the first code not work?

---

<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:** [November 5, 2024, 10:58am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/8 "2024-11-05T10:58:53Z")

</div>

> [@hack3rcon](#):
>
> Why does the first code not work?

The `global` declaration only applies to the scope it’s directly inside. The one outside the `for` loop thus doesn’t affect the `for` loop, so the variables in the `for`-loop will be treated as a local variable, not a global variable.

> [@tecosaur](#):
>
> I think the most helpful suggestion is actually to put code like this within a function.

I second this, but add that a `let` block also puts the code in a local scope and saves an extra function call. If the code doesn’t need to be run in a global scope for persistent variables, then a local scope would work just as well and doesn’t need to deal with rules concerning the global scope (again, because a local scope begins and ends in the same file).

---

<div class="post-metadata">

**Author:** ![hack3rcon](https://avatars.discourse-cdn.com/v4/letter/h/96bed5/32.png) [@hack3rcon](https://discourse.julialang.org/u/hack3rcon)\
**Post date:** [November 5, 2024, 11:05am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/9 "2024-11-05T11:05:52Z")

</div>

🤔  
Not really. Both codes work in julia command, but only the second one works in VSCodium.  
Why?

---

<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:** [November 5, 2024, 11:14am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/10 "2024-11-05T11:14:39Z")

</div>

I can say that both versions should work in the REPL or a notebook’s relaxed rules, otherwise the 1st version would error because of the stricter rules. I’m not sure what you mean by “julia command” so I can’t say anything about that now, but your experience is consistent with and is likely explained by the soft scope discrepancy. Like my earlier example pointed out, the stricter rules also show up when evaluating Julia expressions (this also happens for `include`, `include_string`, `eval`, `@eval`) in the REPL because the relaxed rules can’t interfere that deeply into Julia execution.

---

<div class="post-metadata">

**Author:** ![hack3rcon](https://avatars.discourse-cdn.com/v4/letter/h/96bed5/32.png) [@hack3rcon](https://discourse.julialang.org/u/hack3rcon)\
**Post date:** [November 5, 2024, 11:36am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/11 "2024-11-05T11:36:19Z")

</div>

Hi,  
I mean writing julia in Linux Terminal:

 ![Julia](https://global.discourse-cdn.com/julialang/original/3X/c/c/cc58f39b8fe750d094e6175fde7c70280ae557d1.png)

Codes work in this environment, but not in VSCodium. As far as I know VSCodium uses Julia installed on Linux!  
Where is the problem?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [November 5, 2024, 11:41am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/12 "2024-11-05T11:41:46Z")

</div>

The problem is that one explained in the previous answers. The scoping rules are different depending if you are on the REPL or executing the code by including a file.

---

<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:** [November 5, 2024, 11:52am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/13 "2024-11-05T11:52:28Z")

</div>

And it’s wise to put code into functions. This both makes for a more rational scoping, and ensures the code is compiled when used.

---

<div class="post-metadata">

**Author:** ![hack3rcon](https://avatars.discourse-cdn.com/v4/letter/h/96bed5/32.png) [@hack3rcon](https://discourse.julialang.org/u/hack3rcon)\
**Post date:** [November 5, 2024, 11:54am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/14 "2024-11-05T11:54:19Z")

</div>

Hello,  
Well, that’s too bad. You need an IDE like VSCodium to write a project. If the REPL behavior is different from the IDE, then how do you know that the code you wrote is really wrong? What is the solution?

---

<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:** [November 5, 2024, 11:57am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/15 "2024-11-05T11:57:30Z")

</div>

> [@hack3rcon](#):
>
> What is the solution?

Put the code into functions.

There’s some tips for workflows here:

[https://modernjuliaworkflows.org/](https://modernjuliaworkflows.org/)

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [November 5, 2024, 12:09pm UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/16 "2024-11-05T12:09:33Z")

</div>

How are you running the code exactly?

For instance, if you have some code written in a file (in VSCode(ium)) and execute it by selecting and Control-Enter, it is executed in the REPL and it works with the soft-scope rules. That is, this code:

```julia
a = 0
for i in 1:3
    a = a + 1
end
a

```

can be copied/pasted to the REPL or executed with `Control-Enter` from VSC and it will work.

Yet, another alternative (to which one converges when the codes becomes slightly more complicated, is to put that into a function):

```julia
function test()
    a = 0
    for i in 1:3
        a = a + 1
    end
    a
end

```

The file where that function is written is read using

```julia
julia> using Revise # put this into your startup.jl file

julia> includet("./file.jl")

```

and then the function can be executed with `test()`. After modifying the content of the function, you can just run `test()` again that the new version of the function will be executed.

See: [Development workflow · JuliaNotes.jl](https://m3g.github.io/JuliaNotes.jl/stable/workflow/)

---

<div class="post-metadata">

**Author:** ![hack3rcon](https://avatars.discourse-cdn.com/v4/letter/h/96bed5/32.png) [@hack3rcon](https://discourse.julialang.org/u/hack3rcon)\
**Post date:** [November 6, 2024, 6:27am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/18 "2024-11-06T06:27:31Z")

</div>

Hi,  
Thanks.  
Why does this error only occur in the IDE and not when I use the julia command in the terminal?

---

<div class="post-metadata">

**Author:** ![hack3rcon](https://avatars.discourse-cdn.com/v4/letter/h/96bed5/32.png) [@hack3rcon](https://discourse.julialang.org/u/hack3rcon)\
**Post date:** [November 6, 2024, 6:29am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/19 "2024-11-06T06:29:13Z")

</div>

Hi,  
I use VSCodium.

---

<div class="post-metadata">

**Author:** ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)\
**Post date:** [November 6, 2024, 2:13pm UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/20 "2024-11-06T14:13:03Z")

</div>

> [@hack3rcon](#):
>
> Why does this error only occur in the IDE and not when I use the julia command in the terminal?

“In the IDE” depends on the implementation of the IDE. It’s not a separate idea. Typically, when you run something from vs code, what it’s doing is (the equivalent of) copying code from a file and pasting it into the REPL. When you do this, you get soft scope behavior, as explained.

If you do `julia my_file.jl` from the command line, it’s not interactive, and you get the hard scope behavior.

---

<div class="post-metadata">

**Author:** ![hack3rcon](https://avatars.discourse-cdn.com/v4/letter/h/96bed5/32.png) [@hack3rcon](https://discourse.julialang.org/u/hack3rcon)\
**Post date:** [November 16, 2024, 5:27am UTC](https://discourse.julialang.org/t/variable-scope-concept/122277/21 "2024-11-16T05:27:05Z")

</div>

Hello,  
Thank you so much for your reply.  
I’m a newbie and it’s really hard for me to understand what you said. In my opinion, such behavior is not acceptable. To write big projects, you need an IDE, and such behavior makes the programmer wrong.

[Next page](https://discourse.julialang.org/t/variable-scope-concept/122277.md?page=2)
