Go back to var?

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:

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.

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.

4 Likes

Looking at the last developer survey, 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> 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.

6 Likes

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.

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.

11 Likes