# Variable scope in functions

**URL:** <https://discourse.julialang.org/t/variable-scope-in-functions/7876>\
**Category:** General Usage\
**Tags:** question, scope\
**Created:** [December 20, 2017, 1:27pm UTC](https://discourse.julialang.org/t/variable-scope-in-functions/7876 "2017-12-20T13:27:16Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [December 20, 2017, 1:27pm UTC](https://discourse.julialang.org/t/variable-scope-in-functions/7876/1 "2017-12-20T13:27:16Z")

</div>

I don’t know what to make of this…

In the follow snippet

```julia
const user_mappings, profile_mappings = Dict{Int,Int}(), Dict{Int,Int}()
const user_counter, profile_counter = 0, 0

function data_accessor() :: DataAccessor
  training_data = CSV.read(training_file)

  for row in eachrow(training_data)
    user_id, profile_id, rating = row[:UserID], row[:ProfileID], row[:Rating]
    @show user_counter
    haskey(user_mappings, user_id) || (user_mappings[user_id] = (user_counter += 1))
  end
end

```

a. the line  
`haskey(user_mappings, user_id) || (user_mappings[user_id] = (user_counter += 1))`  
causes an  
`ERROR: LoadError: UndefVarError: user_counter not defined`  
in the previous line, the one saying  
`@show user_counter`.

b. if I comment out the line  
`haskey(user_mappings, user_id) || (user_mappings[user_id] = (user_counter += 1))`  
the loop works

c. if I remove the line  
`@show user_counter`  
but leave the line  
`haskey(user_mappings, user_id) || (user_mappings[user_id] = (user_counter += 1))`  
I still get the `UndefVarError` but at the line  
`haskey(user_mappings, user_id) || (user_mappings[user_id] = (user_counter += 1))`

I have no idea why this happens 😱

```julia
Julia Version 0.6.2
Commit d386e40c17 (2017-12-13 18:08 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin14.5.0)
  CPU: Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, skylake)

```

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 20, 2017, 1:51pm UTC](https://discourse.julialang.org/t/variable-scope-in-functions/7876/3 "2017-12-20T13:51:01Z")

</div>

I think you need a `global user_counter` inside your function.

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [December 20, 2017, 1:52pm UTC](https://discourse.julialang.org/t/variable-scope-in-functions/7876/4 "2017-12-20T13:52:26Z")

</div>

Yes, that’s what I did and it worked: `global user_counter, profile_counter`

I was now re-reading the scope rules in the manual but I still don’t quite get it… Maybe I need to re-re-read…

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 20, 2017, 2:06pm UTC](https://discourse.julialang.org/t/variable-scope-in-functions/7876/5 "2017-12-20T14:06:01Z")

</div>

The statement `user_counter += 1` assigns a value to `user_counter` thus it makes it a local variable. But then it doesn’t find `user_counter` anymore as it is not defined yet when evaluating `user_counter + 1`.

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [December 20, 2017, 2:12pm UTC](https://discourse.julialang.org/t/variable-scope-in-functions/7876/6 "2017-12-20T14:12:25Z")

</div>

Is this what this paragraph explains?

> for loops and Comprehensions have the following behavior: any new variables introduced in their body scopes are freshly allocated for each loop iteration. This is in contrast to while loops which reuse the variables for all iterations. Therefore these constructs are similar to while loops with let blocks inside

So before I attempt to update my variable, when I execute `@show user_counter` it’s actually not showing the `user_counter` variable from the outer scope, but rather a newly defined local variable? Which is set to 0?

I can’t quite find a clear explanation of the behavior…

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 20, 2017, 2:28pm UTC](https://discourse.julialang.org/t/variable-scope-in-functions/7876/8 "2017-12-20T14:28:29Z")

</div>

This due to the scoping of functions, see [https://docs.julialang.org/en/stable/manual/variables-and-scoping/#Hard-Local-Scope-1](https://docs.julialang.org/en/stable/manual/variables-and-scoping/#Hard-Local-Scope-1). The first example shows this. Also note that `x += 1` is equivalent to writing `x = x+1`.

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [December 20, 2017, 5:05pm UTC](https://discourse.julialang.org/t/variable-scope-in-functions/7876/9 "2017-12-20T17:05:52Z")

</div>

Oh yes, you’re right - nice, now I understand. Thank you, very very useful!

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 20, 2017, 7:51pm UTC](https://discourse.julialang.org/t/variable-scope-in-functions/7876/10 "2017-12-20T19:51:07Z")

</div>

Cool! Mark it as solved.

---

<div class="post-metadata">

**Author:** ![Stephen\_Vavasis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephen_vavasis/32/3389_2.png) [@Stephen\_Vavasis](https://discourse.julialang.org/u/Stephen_Vavasis)\
**Post date:** [December 21, 2017, 3:54am UTC](https://discourse.julialang.org/t/variable-scope-in-functions/7876/11 "2017-12-21T03:54:12Z")

</div>

Note that the scoping rules may change in 0.7. In fact, I posted an example with an undefined-variable error in 0.6.1 similar to this one just a few days ago in discourse, and then I found that my example ran without an error in 0.7-nightly. The 0.7 documentation may not have caught up with this language change yet.
