# Go back to var?

**URL:** <https://discourse.julialang.org/t/go-back-to-var/38293>\
**Category:** Internals & Design\
**Created:** [April 27, 2020, 11:23am UTC](https://discourse.julialang.org/t/go-back-to-var/38293 "2020-04-27T11:23:56Z")\
**Posts on this page:** 5\
**Page:** 1

<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:** [April 27, 2020, 11:23am UTC](https://discourse.julialang.org/t/go-back-to-var/38293/1 "2020-04-27T11:23:56Z")

</div>

I debated bringing this up, but I fear if I don’t it will just keep rattling around in my head. I suspect the answer will be “The upheaval from this change would be too much”, so I’m not really expecting it to go into 2.0 but maybe it should be considered.

I’ve been reading github issues on global variable scoping specifically:

> <https://github.com/JuliaLang/julia/issues/28789>
>
> \### Example 1
> 
> This came up with a student who upgraded from 0.6 to 1.0 direct…ly, so never even got a chance to see a deprecation warning, let alone find an explanation for new behavior:
> 
> \`\`\`julia
> julia\> beforefor = true
> true
> 
> julia\> for i in 1:2
> beforefor = false
> end
> 
> julia\> beforefor # this is surprising bit
> true
> 
> julia\> beforeif = true
> true
> 
> julia\> if 1 == 1
> beforeif = false
> end
> false
> 
> julia\> beforeif # Another surprise!
> false
> 
> julia\> function foo()
> infunc = true
> for i in 1:10
> infunc = false
> end
> @show infunc
> end
> foo (generic function with 1 method)
> 
> julia\> foo() # "I don't get this"
> infunc = false 
> \`\`\`
> 
> \### Example 2
> 
> \`\`\`julia
> julia\> total\_lines = 0
> 0
> 
> julia\> list\_of\_files = \["a", "b", "c"\]
> 3-element Array{String,1}:
> "a"
> "b"
> "c"
> 
> julia\> for file in list\_of\_files
> # fake read file
> lines\_in\_file = 5
> total\_lines += lines\_in\_file
> end
> ERROR: UndefVarError: total\_lines not defined
> Stacktrace:
> \[1\] top-level scope at ./REPL\[3\]:4 \[inlined\]
> \[2\] top-level scope at ./none:0
> 
> julia\> total\_lines # This crushs the students willingness to learn
> 0
> \`\`\`
> 
> I "get" why this happens in the sense that I think I can explain, with sufficient reference to the arcana in the manual about what introduces scopes and what doesn't, but I think that this is problematic for interactive use.
> 
> In example one, you get a silent failure. In example two, you get an error message that is very there-is-no-spoon. Thats roughly comparable to some Python code I wrote in a notebook at work today.
> 
> I'm not sure what the rules are in Python, but I do know that generally you can't assign to things at the global scope without invoking global. But at the REPL it does work, presumably because at the REPL the rules are different or the same logic as if they were all are in the scope of function is applied.
> 
> I can't language-lawyer the rules enough to propose the concrete change I would like, and based on Slack this isn't even necessarily perceived as an issue by some people, so I don't know where to go with this except to flag it.
> 
> Cross-refs:
> \#19324
> https://discourse.julialang.org/t/repl-and-for-loops-scope-behavior-change/13514
> https://stackoverflow.com/questions/51930537/scope-of-variables-in-julia

> <https://github.com/JuliaLang/julia/pull/33864>
>
> After thinking about it off and on for quite a while, @StefanKarpinski and I mor…e-or-less decided that the best way to change the REPL scope situation (if at all) is just to bring back what v0.6 did. That's what SoftGlobalScope and IJulia already do (albeit somewhat approximately; implementing it internally it's much easier to get it 100%), and seems less disruptive than introducing a \*third\* behavior.
> 
> This needs to be finished up but is ready to try. Please give it a whirl.
> 
> I'm not sure what the best interface to it is; it seemed easiest just to drop a special expression in the AST itself.
> 
> fixes #28789

And @jeff.bezanson made the comment:

> Do you want to write `var x = 0` to introduce every variable? That would also “fix” this, and be more like other languages.

And I feel like the decision to NOT have to declare the variable before hand is causing this issue.

I’ve spent my entire adult life (and some of my teen years) putting something in front of a variable assignment to let the compiler know I’m defining a variable for **this** scope. Whether is be “int”, “var”, “let” or now with Julia “local” and I never found it that onerous. Hence the reason I put `local` in front of all my variable declarations.

I’m assuming one of the reasons to not require local in front of a variable declaration was because “It was obvious you where declaring a variable with the assignment”. However the issues raise show that is **not** obvious, sometimes you want to change a variable in a parent scope and sometimes you want to declare a new variable…the compiler can only infer what the developer wanted.

So requiring that when declaring a new variable you prefix it with local would clear up the confusion for the compiler, if the assignment wasn’t prefixed with local, and if the variable is not defined in a parent scope, it’s a variable not found, otherwise it’s a new variable.

All that being said it is nice in the REPL to be able to declare a variable just with the assignment. I tend to view the global scope as special anyway not that it’s global but that it appears global because it just happens to be the parent of all other scopes. So having the global scope not require local/global or ignoring them if they are included doesn’t cause a concern with me. Using local in the global scope is meaningless because there is no parent scope to keep separate from.

Thanks for listening, feel free to tell me I’m nuts.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [April 27, 2020, 1:01pm UTC](https://discourse.julialang.org/t/go-back-to-var/38293/2 "2020-04-27T13:01:51Z")

</div>

> [@pixel27](#):
>
> Thanks for listening, feel free to tell me I’m nuts.

A lot of valid choices are possible when designing a programming language, with various trade-offs. Julia chose a particular one from the beginning which has some advantages, and while it has caused some difficulties, a lot of work has been done on mitigating them.

I think that we should explore how well #33864 handles the issue for a while before even thinking about changing this again.

---

<div class="post-metadata">

**Author:** ![tfehring](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tfehring/32/14271_2.png) [@tfehring](https://discourse.julialang.org/u/tfehring)\
**Post date:** [April 27, 2020, 4:56pm UTC](https://discourse.julialang.org/t/go-back-to-var/38293/3 "2020-04-27T16:56:11Z")

</div>

> [@pixel27](#):
>
> I’ve spent my entire adult life (and some of my teen years) putting something in front of a variable assignment to let the compiler know I’m defining a variable for **this** scope. Whether is be “int”, “var”, “let” or now with Julia “local” and I never found it that onerous. Hence the reason I put `local` in front of all my variable declarations.

Looking at the last [developer survey](https://julialang.org/images/2019-julia-user-developer-survey.pdf), the vast majority of Julia developers seem to be coming from one or more of Python, R, or Matlab. In all three of those languages, `n = 1` is valid syntax to declare the variable `n` and initialize it to `1`. It’s a matter of familiarity, not just onerousness.

I also strongly feel that #33864 was the correct decision, since it standardizes the behavior that `=` looks for the variable in the enclosing scope before allocating and initializing it locally, unless you override that behavior with `local`. In 1.4:

```julia
julia> a = 1
       for i = 1:2
           a = 2
       end
       a
1
julia> function f()
           a = 1
           for i = 1:2
               a = 2
           end
           a
       end
       f()
2

```

In 1.5, both expressions result in the value 2. This is the “default” (i.e., no `let`/`local`) behavior I’d expect, I’d hazard a guess that it’s the behavior most people would expect, and it’s consistent with both Python and R.

You may be right about this behavior not being obvious, but (starting in 1.5) it’s straightforward and internally consistent, and the way to opt out of it (`local`) is intuitive.

---

<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:** [April 27, 2020, 5:24pm UTC](https://discourse.julialang.org/t/go-back-to-var/38293/4 "2020-04-27T17:24:17Z")

</div>

> [@tfehring](#):
>
> but (starting in 1.5) it’s straightforward and internally consistent,

One of the thing that did worry me…but I may have this wrong, there where a lot of ideas being thrown around was that with this the new/old behavior will just be for the REPL so that something typed into the REPL will behave differently that if the same text where entered into a .jl file and included. If that is true, that seems wrong to me.

---

<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:** [April 27, 2020, 6:05pm UTC](https://discourse.julialang.org/t/go-back-to-var/38293/5 "2020-04-27T18:05:42Z")

</div>

[https://docs.julialang.org/en/v1.5-dev/manual/variables-and-scoping/#On-Soft-Scope-1](https://docs.julialang.org/en/v1.5-dev/manual/variables-and-scoping/#On-Soft-Scope-1)

In particular:

> An important property of this design is that any code that executes in a file without a warning will behave the same way in a fresh REPL. And on the flip side, if you take a REPL session and save it to file, if it behaves differently than it did in the REPL, then you will get a warning.

Also: enough on this already. Try 1.5 for a while before spitballing more changes. Requiring `var` would be absurdly disruptive.
