# Local variable inside a loop: why it ERRORs

**URL:** <https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [September 18, 2025, 11:07pm UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501 "2025-09-18T23:07:25Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [September 18, 2025, 11:07pm UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/1 "2025-09-18T23:07:25Z")

</div>

Dear all:  
I wonder why is the `UndefVarError`, and, is the `Suggestion` accurate?

```julia
julia> function test(C)
           count = 1
           v = Function[]
           while count < C
               local item
               f = function()
                   println("I'm ", item[])
               end
               push!(v, f)
               if count == 1
                   item = [count]
               else
                   item[] += 1
               end
               map(x -> x(), v)
               count += 1
           end
       end

julia> test(2)
I'm 1

julia> test(3)
I'm 1
ERROR: UndefVarError: `item` not defined in local scope
Suggestion: check for an assignment to a local variable that shadows a global of the same name.
Stacktrace:
 [1] test(C::Int64)
   @ Main .\REPL[1]:13
 [2] top-level scope
   @ REPL[3]:1

```

How to analyze the `item`, is it a local variable in one pass, or is it a local variable in all `C-1` passes.  
(by “pass” I mean _one go_ from top to bottom within the while).

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [September 18, 2025, 11:20pm UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/2 "2025-09-18T23:20:01Z")

</div>

It **always** helps to form a minimal reproducible example. Get rid of all unnecessary lines so you can focus on the underlying issue.

Here’s one example:

```Julia
julia> function test()
           for i in 1:2
               local item
               if i == 1
                   item = [i]
               else
                   item[] += 1
               end
           end
       end
test (generic function with 2 methods)

julia> test()
ERROR: UndefVarError: `item` not defined in local scope
Suggestion: check for an assignment to a local variable that shadows a global of the same name.
Stacktrace:

```

One the first iteration, you declare `local item` and initialise it.

On the second iteration, you declare a new `local item`, and then attempt `item[] += 1`, which tries to read `item[]`. But because of `local item`, the variable does not persist between iterations and so it doesn’t exist in iteration 2.

Change where you put the `local`:

```Julia
julia> function test()
           local item
           for i in 1:2
               if i == 1
                   item = [i]
               else
                   item[] += 1
               end
           end
           return item
       end
test (generic function with 2 methods)

julia> test()
1-element Vector{Int64}:
 2

```

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [September 19, 2025, 10:07am UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/3 "2025-09-19T10:07:20Z")

</div>

I’m a fussy person… thereby open a PR to modify the doc

> <https://github.com/JuliaLang/julia/pull/59602#issue-3433736765>
>
> \`\`\`julia
> function main()
> c = 0
> while c \<= 2
> … c += 1
> if c \<= 1
> local d = c
> end
> println("In the $c-th iteration:")
> println("d = $d")
> end
> end
> 
> julia\> main()
> In the 1-th iteration:
> d = 1
> In the 2-th iteration:
> ERROR: UndefVarError: \`d\` not defined in local scope
> \`\`\`

I think it’s misleading to say “`while`/`for` introduces _a_ local scope”.

---

<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:** [September 19, 2025, 1:17pm UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/4 "2025-09-19T13:17:25Z")

</div>

> [@WalterMadelim](#):
>
> I think it’s misleading to say “`while`/`for` introduces _a_ local scope”.

Would you say that about a function also, that it doesn’t introduce _a_ local scope?

```julia
function foo(i)
    if i == 0
        a = 10
    else
        a += 1
    end
    return a
end
julia> foo(0)
10

julia> foo(1)
ERROR: UndefVarError: `a` not defined in local scope

```

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [September 19, 2025, 1:22pm UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/5 "2025-09-19T13:22:29Z")

</div>

There is no ambiguity in this case—the three `a`’s are the same _name_. This case is not confusing to users.

This is not the case for `while`/`for`, people needs to understand that if you have 10 iterations, then the local (user-specified) names in the loop body are **not identical**.

(My thoughts are also updated in the Github link above)

---

<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:** [September 19, 2025, 1:33pm UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/6 "2025-09-19T13:33:54Z")

</div>

Isn’t this in the manual:

> Note that the local scope of a for loop body is no different from the local scope of an inner function.  
> [Scope of Variables · The Julia Language](https://docs.julialang.org/en/v1/manual/variables-and-scoping/#local-scope)

It’s the loop _body_ which has its own scope, so for scope purposes it’s the same as calling a function repeatedly.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [September 19, 2025, 1:50pm UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/7 "2025-09-19T13:50:28Z")

</div>

> Note that the local scope of a for loop body is no different from the local scope of an inner function. This means that we could rewrite this example so that the loop body is implemented as a call to an inner helper function and it behaves the same way:

This may be theoretically equivalent. But would anyone write this conversion in practice? e.g. due to performance issues? Is the plain loop faster? I’m not very clear about this.

Anyway, I think the stress is on learning a skill to producing the predictable final result.

To be honest I’m having difficulty understanding some parts of that manual, e.g.

```julia
begin
    local c
    c += 1
end

```

It says begin block will not introduce a scope. But why is here a `local`?

Anyway, I have no chance using `begin`, so I would skip it.

* * *

And `break` `continue` is exclusive to `for`/`while`.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [September 20, 2025, 1:44pm UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/8 "2025-09-20T13:44:34Z")

</div>

> [@sgaure](#):
>
> > [@WalterMadelim](#):
> >
> > I think it’s misleading to say “`while`/`for` introduces _a_ local scope”.
> 
> Would you say that about a function also, that it doesn’t introduce _a_ local scope?

I think your idea is correct ✅.

* * *

I re-express my thoughts in the following region:

If you ask a new user this question

- how many **different** entities _named_ `item` exist in the following code

```julia
function test()
    item = 0
    for i in 1:2
        local item
        if i == 1
            item = [i]
        else
            item[] += 1
        end
    end
end
test()

```

It is possible for him to answer: Oh, the `function test` introduce a local scope, there is one outer `item` being associated to `0`. Oh, I also see the `for` loop introduce an inner local scope and there is also an `local item` inside. So if there are no global name `item` elsewhere, the conclusion is:

- there are **2** different entities named `item` here, both are non-global.

(Yes, surely—I asked ChatGPT, who answered **2**.)

But in reality, the proper answer is **3** , given Oscar’s answer in #2 post.

* * *

Anyway, I think my comprehension still needs to be advanced—therefore I give up the Github actions, giving way to people who are more experienced. 😊

* * *

Edit: I took a closer look at ChatGPT’s answer, and find it’s even worse

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

---

<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:** [September 20, 2025, 4:00pm UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/9 "2025-09-20T16:00:30Z")

</div>

> [@WalterMadelim](#):
>
> But in reality, the proper answer is **3** , given Oscar’s answer in #2 post.

An if you call the function twice, it’s … 6? Or do you want repeated executions of the scope in the loop body to count multiple times, but not repeated execution of the scope in the function? What about repeated execution of `let`? Are there 10 scopes with `b` in this function?

```julia
function f()
    i = 1
    a = 0
    @label L
    let b = i^2
        a += b
    end
    i += 1
    if i < 10
        @goto L
    end
    return a
end

```

Perhaps in the sense of dynamic scopes, but not the lexical scopes which are used in julia.

---

<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:** [September 20, 2025, 5:14pm UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/10 "2025-09-20T17:14:40Z")

</div>

> [@WalterMadelim](#):
>
> It says begin block will not introduce a scope. But why is here a `local`?

The preceding description is pretty much all there is to it:

> If a top-level expression contains a variable declaration with keyword `local` , then that variable is not accessible outside that expression.

So while a `begin` block doesn’t make a local scope, a `local` declaration makes a variable only last in that scope, similar to how uncaptured local variables only last in their home local scope. The Manual currently does not describe this as a local variable, whether directly or indirectly. However, it does currently behave similarly to a local variable, even if the capture and boxing are implemented differently for global functions.

```julia-auto
julia> begin
        x = 1 # normal global
        f() = x
        print(f(), ", ")
        let # rules say this would reassign outer locals
          x = 10
        end
        local y = 2
        g() = y
        println(g())
        let
          y = 20
        end
        nothing
       end
1, 2

julia> f(), g() # local y got reassigned
(1, 20)

```

---

<div class="post-metadata">

**Author:** ![Boris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/boris/32/3306_2.png) [@Boris](https://discourse.julialang.org/u/Boris)\
**Post date:** [September 26, 2025, 2:02pm UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/11 "2025-09-26T14:02:01Z")

</div>

I have always found scopes in Julia confusing as a non-programmer and a noob, but saying that a for/while loop introduces a new scope on each iteration cannot be true, or did I completely misunderstand your PR?

> …`while` defines a distinct [local scope](@ref scope-of-variables) **for each** of its iteration…

In your original code you are just redefining ‘item’ with `local item` at each iteration. I don’t see how this has anything to do with scopes, it is an error of the programmer.

It is like writing

```julia-auto
for i in 1:n
    x = 0
    x = x+1
end

```

and then wondering why x at the end of the loop is always 1 instead of n.

---

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [September 26, 2025, 3:23pm UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/12 "2025-09-26T15:23:06Z")

</div>

> [@Boris](#):
>
> In your original code you are just redefining ‘item’ with `local item` at each iteration. I don’t see how this has anything to do with scopes

As far as I understand, writing `local var` does not define a new (uninitialised) variable `var`, it just declares that all appearances of `var` in the current scope refer to a different variable than any `var` in the outer scope. In particular, you can have

```julia-repl
julia> function f()
           local i
           i = 2
           local i # Does not create a new variable i; i below remains at 2
           println(i)
       end;

julia> f()
2

```

and

```julia-repl
julia> function g()
           i = 1
           for j = 1:1
               i = -1 # Not the same i as above
               local i # even though we only declare it here
           end
           return i # Still 1
       end;

julia> g()
1

```

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [September 27, 2025, 2:16am UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/13 "2025-09-27T02:16:01Z")

</div>

> [@Boris](#):
>
> I have always found scopes in Julia confusing as a non-programmer and a noob, but saying that a for/while loop introduces a new scope on each iteration cannot be true

The concept “a scope being local” and “a variable being local” are different. I regret opening that.

> [@Boris](#):
>
> It is like writing
> 
> ```julia-auto
> for i in 1:n
> x = 0
> x = x+1
> end
> 
> ```
> 
> and then wondering why x at the end of the loop is always 1 instead of n.

No this situation is not alike in any way. There is no confusion in your case because you are re-associating `x` to `0` every iteration and clearly the `x` in `x = x+1` is identical to the `x` in `x = 0`, regardless of whether `x` being local or global.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [September 27, 2025, 2:20am UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/14 "2025-09-27T02:20:59Z")

</div>

> [@Boris](#):
>
> I have always found scopes in Julia confusing

In retrospect, I think julia’s style choice is reasonable. And I now accept it.  
I don’t mind at all typing some `local` keyword when it’s necessary, because functions itself should be short—otherwise it’s the user writing cumbersome code.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [September 27, 2025, 12:30pm UTC](https://discourse.julialang.org/t/local-variable-inside-a-loop-why-it-errors/132501/15 "2025-09-27T12:30:41Z")

</div>

> [@WalterMadelim](#):
>
> I don’t mind at all typing some `local` keyword when it’s necessary,

With that just said, I’ve just spend 3 hours debugging a weird ERROR:

```julia
julia> f()
ERROR: BoundsError: attempt to access Float64 at index [2]
Stacktrace:
 [1] indexed_iterate(I::Float64, i::Int64, state::Nothing)
   @ Base .\tuple.jl:168

```

finally finding that the problematic line is here:

```julia
function f()
    ...
    local c = s.a, b = 4.0
end

```

😭  
Oh no. I guess I won’t write `=` in conjunction with `local` any longer (which was `let`’s syntax). It’s a bad habit.
