# Scoping in nested functions - Why am I not getting an error?

**URL:** <https://discourse.julialang.org/t/scoping-in-nested-functions-why-am-i-not-getting-an-error/39354>\
**Category:** General Usage\
**Tags:** question\
**Created:** [May 12, 2020, 3:34pm UTC](https://discourse.julialang.org/t/scoping-in-nested-functions-why-am-i-not-getting-an-error/39354 "2020-05-12T15:34:28Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![StevenWhitaker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevenwhitaker/32/9749_2.png) [@StevenWhitaker](https://discourse.julialang.org/u/StevenWhitaker)\
**Post date:** [May 12, 2020, 3:34pm UTC](https://discourse.julialang.org/t/scoping-in-nested-functions-why-am-i-not-getting-an-error/39354/1 "2020-05-12T15:34:28Z")

</div>

I am confused about the behavior of scoping when using a nested function. I am using Julia 1.4.1.

MWE:

```julia
function main()

    function doit()
        A = ones(Int, 2) # <-- I expected this to introduce a new A within the scope of doit
        return A
    end

    doit()
    display(A) # <-- Why is this not an error? I haven't defined A yet
    A = [1, 2, 3] # <-- Now A is defined
    display(A)
    doit()
    display(A) # <-- Why is A overwritten? I didn't assign it to the output of doit()

end

```

Output:

```julia
julia> main()
2-element Array{Int64,1}: # Expected an error for undefined A
 1
 1
3-element Array{Int64,1}: # This is what I expected
 1
 2
 3
2-element Array{Int64,1}: # Expected [1, 2, 3] again
 1
 1

```

It looks like there is no new scope introduced for `doit`. Is that correct? Can someone explain why that is, or if I am misunderstanding something?

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [May 12, 2020, 3:42pm UTC](https://discourse.julialang.org/t/scoping-in-nested-functions-why-am-i-not-getting-an-error/39354/2 "2020-05-12T15:42:45Z")

</div>

My understanding is that when Julia compiles main() it notices that `A` gets defined in main(). Therefor when the child function set `A` it’s actually setting A in the parent context. The compiler doesn’t care when A is set just that it was set.

One way to avoid this situation is that when defining the variable prefix it with `local` that will ensure that the variable is, well, local. So if you did `local A = ones(Int, 2)` then **that** A would be local to doit() and you would get the expected error.

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [May 12, 2020, 3:52pm UTC](https://discourse.julialang.org/t/scoping-in-nested-functions-why-am-i-not-getting-an-error/39354/3 "2020-05-12T15:52:07Z")

</div>

This is documented in the manual:  
[https://docs.julialang.org/en/v1/manual/variables-and-scoping/#Local-Scope-1](https://docs.julialang.org/en/v1/manual/variables-and-scoping/#Local-Scope-1)

> Note that _nested functions_ can modify their parent scope’s _local_ variables:
> 
> ```julia
> julia> x, y = 1, 2;
> 
> julia> function baz()
> x = 2 # introduces a new local
> function bar()
> x = 10 # modifies the parent's x
> return x + y # y is global
> end
> return bar() + x # 12 + 10 (x is modified in call of bar())
> end;
> 
> julia> baz()
> 22
> 
> julia> x, y # verify that global x and y are unchanged
> (1, 2)
> 
> ```
> 
> The reason to allow modifying local variables of parent scopes in nested functions is to allow constructing [`closures`](https://en.wikipedia.org/wiki/Closure_%28computer_programming%29) which have private state

In your example, the function is defined before the variable that it modifies, but the compiler doesn’t care of that — just as in the case of variables defined in the global scope.

---

<div class="post-metadata">

**Author:** ![StevenWhitaker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevenwhitaker/32/9749_2.png) [@StevenWhitaker](https://discourse.julialang.org/u/StevenWhitaker)\
**Post date:** [May 12, 2020, 3:58pm UTC](https://discourse.julialang.org/t/scoping-in-nested-functions-why-am-i-not-getting-an-error/39354/4 "2020-05-12T15:58:07Z")

</div>

Yes, but in the manual `x` is defined _before_ the nested function is defined. In my example, `A` was defined after the definition of the nested function. I understand why the example in the manual works as it does because `x` was created before the nested function was. I don’t understand why the nested function in my example captures a variable I haven’t defined yet.

EDIT: Sorry, I responded thinking I had already scrolled to the end of your post, so I missed

> In your example, the function is defined before the variable that it modifies, but the compiler doesn’t care of that — just as in the case of variables defined in the global scope.

That’s a good point.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [October 15, 2021, 4:05pm UTC](https://discourse.julialang.org/t/scoping-in-nested-functions-why-am-i-not-getting-an-error/39354/5 "2021-10-15T16:05:09Z")

</div>

Also note that one doesn’t have to assign a value to the variable in the parent function, one can just declare it via `local`:

```julia
function baz()
    local x
    function bar()
        x = 2
    end
    bar()
    x
end

baz() # returns 2

```

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [October 16, 2021, 2:30pm UTC](https://discourse.julialang.org/t/scoping-in-nested-functions-why-am-i-not-getting-an-error/39354/6 "2021-10-16T14:30:03Z")

</div>

I just noticed that this isn’t type stable.

```julia
function baz()
    local x
    function bar()
        x = 2
    end
    bar()
    x
end

baz() # returns 2

```

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

Is there a better way of doing this?

---

<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:** [October 16, 2021, 6:41pm UTC](https://discourse.julialang.org/t/scoping-in-nested-functions-why-am-i-not-getting-an-error/39354/7 "2021-10-16T18:41:33Z")

</div>

This does not address exactly what you are asking, but I think that having a closure that modifies the closed over variables is always walking on a danger zone. I would advice to simply don’t do it, and use patterns like:

```julia
julia> function baz()
           a = 5
           function bar()
               x = 2 + a # do not modify a here
           end
           y = bar()
           y
       end
baz (generic function with 1 method)

julia> @code_warntype baz()
Variables
  #self#::Core.Const(baz)
  y::Int64
  bar::var"#bar#5"{Int64}
  a::Int64

Body::Int64
1 ─ (a = 5)
│ %2 = Main.:(var"#bar#5")::Core.Const(var"#bar#5")
│ %3 = Core.typeof(a::Core.Const(5))::Core.Const(Int64)
│ %4 = Core.apply_type(%2, %3)::Core.Const(var"#bar#5"{Int64})
│ (bar = %new(%4, a::Core.Const(5)))
│ (y = (bar::Core.Const(var"#bar#5"{Int64}(5)))())
└── return y::Core.Const(7)

```
