# Another possible solution to the global scope debacle

**URL:** <https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894>\
**Category:** Internals & Design\
**Created:** [October 4, 2018, 6:14pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894 "2018-10-04T18:14:07Z")\
**Posts on this page:** 20\
**Page:** 4

<div class="post-metadata">

**Author:** ![swissr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/swissr/32/208_2.png) [@swissr](https://discourse.julialang.org/u/swissr)\
**Post date:** [October 5, 2018, 10:28am UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/61 "2018-10-05T10:28:54Z")

</div>

Would it be possible to just re-introduce the warning/error messages in the REPL but otherwise keep the new behaviour from [#19324](https://github.com/JuliaLang/julia/pull/19324)?

In this way, the examples ([IanNZ / 28789)](https://github.com/JuliaLang/julia/issues/28789) loose their gravity as the error/warning message just tells me what to do, i.e. prepend the variable with `global`. The silent failure gives a warning, the ‘real’ failure an error, for example:

```julia
julia> for i in 1:2
         beforefor = false
       end
┌ Warning: `implicit assignment to global variable `beforefor``.
│ Use `global beforefor` instead.
└

julia> for file in list_of_files
         # fake read file
         lines_in_file = 5
         total_lines += lines_in_file
       end
┌ Error: `implicit assignment to global variable `total_lines``.
│ Use `global total_lines` instead.
└

```

I’m not sure I like (yet?) the need to write `global` at some places but on the other hand it seems a coherent rule to access global variables and loosing the hard/soft scope distinction was nice (this distinction has also been criticized). But more importantly, I think the current behaviour has been choosen and I don’t hope that there is now a rush to change it again (before 2.0 and after careful consideration)!

---

<div class="post-metadata">

**Author:** ![haberdashPI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/haberdashpi/32/26337_2.png) [@haberdashPI](https://discourse.julialang.org/u/haberdashPI)\
**Post date:** [October 5, 2018, 12:40pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/62 "2018-10-05T12:40:18Z")

</div>

Just wanted to add my support for @jeff.bezanson’s scoping rule proposed here. I also think it’s reasonable to make an exception to the promise not to introduce breaking changes and roll this change out in some version of 1.x.

---

<div class="post-metadata">

**Author:** ![jebej](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jebej/32/1784_2.png) [@jebej](https://discourse.julialang.org/u/jebej)\
**Post date:** [October 5, 2018, 1:14pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/63 "2018-10-05T13:14:20Z")

</div>

I was asking whether, in a common case where people would be operating on some variables in a loop at the REPL, e.g.

```julia
B = loadsomedata("data")
s = 0
for i = 1:length(B)
    s += somefunction(B[i])
end

```

if that would become slow compared to 0.6 - 0.7, given that more variables will be treated as globals.

---

<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:** [October 5, 2018, 1:31pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/64 "2018-10-05T13:31:52Z")

</div>

I have been thinking about this rule since I read the post this morning, and I think it would be a nice solution, and handle the various corner cases in a way that is both

1. easy to reason about statically (just from looking at the code),
2. does not depend on the variable being defined,
3. is a good approximation of what people like to see intuitively.

It would be great if someone could prepare a table of various relevant mini-examples, and discuss

1. what 0.6 did (optionally, but it would be helpful),
2. what happens in 1.0,
3. what the rule proposes.

Eventually some of these could end up in the documentation.

Eg to continue #28789 (because it is locked), my understanding is that under the new rule,

```julia
julia> for i in 1:2
         beforefor = false
       end

julia> beforefor
false

```

regardless whether `beforefor` was assigned before;

and scope _inside_ functions would just work as in 1.0. Is this correct?

(Also, now that a proposal is in sight and people have calmed down, could we you please unlock the issue?)

---

<div class="post-metadata">

**Author:** ![non-Jedi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/non-jedi/32/3645_2.png) [@non-Jedi](https://discourse.julialang.org/u/non-Jedi)\
**Post date:** [October 5, 2018, 1:36pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/65 "2018-10-05T13:36:16Z")

</div>

I don’t have a super strong opinion either way on what the right forward course is for this problem (part of me really likes the current behavior), but the suggestion here definitely seems reasonable, so I’m not opposed to it.

That said, I’m strongly against making any breaking change and continuing to call the language Julia 1.x rather than Julia 2.x. Sem ver really is just supposed to be a way of communicating with users, and if the 1.x series of some software has a misfeature that is noticed as quickly as this global scope debacle has been, it’s a very reasonable approach to release a 2.0 version relatively quickly. That’s why we have semver in the first place to facilitate clean communication of things like this; if we continue to call software with a breaking feature change by the same major version, we lose most all the benefit of semver. Basically, we have to release a new version of Julia to fix this no matter what; we should call the new breaking Julia version by its proper semver name: 2.0.

If a quick 2.0 is really _completely_ off the table, I think @swissr’s suggestion is the most reasonable way forward (I’m definitely against introducing differences between how the REPL behaves and how scripts behave).

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [October 5, 2018, 1:59pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/66 "2018-10-05T13:59:42Z")

</div>

Just to be clear, IJulia _already_ does a variant of this (automatically inserting `global` keywords as needed in global scope). So far there has not been a single complaint that this is different from scripts/files. Possibly this is because once you get to the point of putting code into a file you are usually writing functions.

So I don’t think it would be a big problem if the new behavior were in the REPL in 1.1 and opt-in elsewhere. Certainly we would get fewer confused queries than now, especially if the error message for undefined variables in global scopes is improved also.

---

<div class="post-metadata">

**Author:** ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)\
**Post date:** [October 5, 2018, 2:06pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/67 "2018-10-05T14:06:31Z")

</div>

In that code in the REPL, `B` and `s` would be global in all versions of julia. The only small difference is in 1.0, which gives an error, and you have to write `global s += somefuction(B[i])`. Making `s` local to the loop would not work, since then you couldn’t update the global `s` you want to use outside the loop.

---

<div class="post-metadata">

**Author:** ![jebej](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jebej/32/1784_2.png) [@jebej](https://discourse.julialang.org/u/jebej)\
**Post date:** [October 5, 2018, 2:26pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/68 "2018-10-05T14:26:23Z")

</div>

I see thanks. I though 0.6 might have been using a trick to “make the globals local” in order to act on them in the loop efficiently.

If you have the time then, would you mind explaining how the proposed scheme is different from 0.6?

---

<div class="post-metadata">

**Author:** ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)\
**Post date:** [October 5, 2018, 2:33pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/69 "2018-10-05T14:33:30Z")

</div>

In 0.6:

```julia
julia> x = 0;

julia> for i = 1:2
         x = i
       end

julia> x
2

julia> for i = 1:2
         y = i
       end

julia> y
ERROR: UndefVarError: y not defined

```

Here `y` was local to the loop since no global `y` had been assigned yet. In the proposal in this thread, `y` in the loop would also be global.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [October 5, 2018, 2:43pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/70 "2018-10-05T14:43:27Z")

</div>

I have a suggestion: would it be possible to refine the terminology? The way I understand the issue is that there are variables that come into local scopes from enclosing scopes. They are not necessarily global, they are just not local to the interior scope. If I’m right, it might be worthwhile not to refer to such variables as “global”, but something else (outer?).

---

<div class="post-metadata">

**Author:** ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)\
**Post date:** [October 5, 2018, 2:47pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/71 "2018-10-05T14:47:15Z")

</div>

Yes, if you’re just talking about referencing a variable from an enclosing scope, it’s best to call it it an outer variable. However this issue truly only affects global variables. Nothing has changed or will change about how accessing variables in outer scopes works if the variables are local.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [October 5, 2018, 2:55pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/72 "2018-10-05T14:55:58Z")

</div>

I’m hesitant to express an opinion that is clearly contrary to the mainstream here, but I really _like_ the way 1.0 works in regards to scope. It has helped me develop a sense of code isolation, to the point of looking at

```julia
julia> x = 0;

julia> for i = 1:2
         x = i
       end

julia> x

```

and immediately expecting to get `0`. I want isolation as much as possible, and a clear notion that global bindings is not something to use as a work registers, counters, etc. Globals are to be feared, in a way, and to be left untouched once they are defined. I somehow like this notion, and it has served me well so far. This is just a matter of education, not design, I think. So, for what it’s worth, I cast my vote to actually do nothing about this issue.

---

<div class="post-metadata">

**Author:** ![jebej](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jebej/32/1784_2.png) [@jebej](https://discourse.julialang.org/u/jebej)\
**Post date:** [October 5, 2018, 3:01pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/73 "2018-10-05T15:01:12Z")

</div>

For anything serious, wouldn’t you be putting everything in a function anyway?

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [October 5, 2018, 3:37pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/74 "2018-10-05T15:37:36Z")

</div>

Oops, sorry. I thought the issue was to unify treatment of global variables and variables in outer scopes relative to inner scopes.

---

<div class="post-metadata">

**Author:** ![anon94023334](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@anon94023334](https://discourse.julialang.org/u/anon94023334)\
**Post date:** [October 5, 2018, 4:25pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/75 "2018-10-05T16:25:07Z")

</div>

> [@StefanKarpinski](#):
>
> I’m afraid I don’t think that’s an option given the commitment we’ve made to not breaking user code in Julia 1.x; even deprecations are really stretching it.

I agree with this, but then

> Julia 2.0 is probably several years away at this point.

suggests that our hands are effectively tied by some general sense that we can’t release new versions before some designated time has passed, which puts us at an extreme disadvantage of our own making.

We should adopt one, but not both, of these guidelines.

(Edited to add: please feel free to split this discussion out of this main thread if it’s distracting, but I’m really interested in this issue since we’re facing it in LightGraphs as well. SemVer isn’t time-based, it’s feature/contract-based, and there’s this strong tendency to conflate the two properties.)

---

<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:** [October 5, 2018, 4:43pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/76 "2018-10-05T16:43:03Z")

</div>

What you want to do here is clearly:

```julia
B = loadsomedata("data")
s = 0
for i = 1:length(B)
    global s += somefunction(B[i])
end

```

In this example, if `s` is local then the code doesn’t work, so that’s not what you intend (there are other situations where it would make sense for `s` to be local, however). Regardless of _how_ you write that, it has the same performance—because it’s doing the same exact thing. The only question is whether you need to write the `global` keyword or not (and what the rules are about when you do or don’t need to write `global` or `local` in general). There’s no way that different syntax can make the same code faster or slower. @Liso brought that up as a possibility, but it’s not a possibility, this discussion does not have any relevance to performance.

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [October 5, 2018, 4:50pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/77 "2018-10-05T16:50:41Z")

</div>

Violating SemVer is bad, it breaks the semver promises about compact.

I think anyone who follows closely knew there would be problems that couldn’t b e fixed without breaking changes.  
And part of maturing into a 1.0 version is becoming comfortable that no-longer can we just fix them whenever we want.  
That time is behind us now.  
And that is OK.

I am much more comfortable with the idea of whatever behaviour being on be default in the REPL,  
And opt in, everywhere else.  
`Using Future: scoping`  
Then in 2.0 we can have the nice solution.

The REPL already behaves a little different since it implicitly `using InteractiveUtils` as well as `Base` and `Core`.  
That actually catch’s me out surprisingly often.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [October 5, 2018, 5:00pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/78 "2018-10-05T17:00:24Z")

</div>

To understand the issues a little bit better: when we say global, do we mean variables defined at the top level (REPL), or variables defined outside of functions?

In a way, it seems to me that variables defined outside of functions are really of the same kind, no matter whether they are defined in the REPL or in files (modules). These variables are always defined in modules. (The top-level variables are defined in `Main`, aren’t they?)

---

<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:** [October 5, 2018, 5:12pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/79 "2018-10-05T17:12:25Z")

</div>

As a matter of pure syntax, this is the most automatically fixable thing possible. We can completely automatically fix this with 100% accuracy in every registered Julia package. Just rewrite every instance of top-level scope code that depends on the 1.0 behavior to have an explicit `local` annotation. People seem to mostly agree that changing this in the REPL and IJulia would be fine (in fact, it’s already changed in IJulia via SoftGlobalScope.jl). That leaves only the case of non-interactive scripts that have been written since 1.0 was released, which strikes me, as I said, as an small risk, especially if we do a 1.1 warning followed by a 1.2 error, followed by actually changing the behavior in 1.3. Even for that small sliver of cases, this change would leave most scripts still working correctly, but with a few more global bindings than intended. You have to use a name as a global, then use it as a local in a top-level non-function scope constrict (intentionally—some cases will be accidental, in which case this will fix a bug), and then access the global again, expecting it to have the value it had before the middle usage. Changing in the other direction—what the 0.6 to 1.0 change did—was was more likely to break things.

---

<div class="post-metadata">

**Author:** ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)\
**Post date:** [October 5, 2018, 5:35pm UTC](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894/80 "2018-10-05T17:35:25Z")

</div>

Variables defined outside functions are all global, whether in the REPL or not. We’re just considering using different syntax in the REPL for greater interactive convenience without breaking larger programs.

[Previous page](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894.md?page=3)

[Next page](https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/15894.md?page=5)
