# New scope solution

**URL:** https://discourse.julialang.org/t/new-scope-solution/16707
**Category:** Internals & Design
**Tags:** proposal
**Created:** [October 23, 2018, 8:58pm UTC](https://discourse.julialang.org/t/new-scope-solution/16707 "2018-10-23T20:58:16Z")
**Posts on this page:** 20
**Page:** 10

<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: [January 29, 2019, 1:20am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/185 "2019-01-29T01:20:51Z")

</div>

Yes, this is the trade off that Python makes. It’s not a terrible one. Recall, however, how much trouble Python has had with the scope of variables in comprehensions as a result. If you choose the Python design then you either have lots of unexpected leaking of comprehension variables or loops and comprehensions behave very differently. So it’s no panacea either. In Julia, comprehensions were a very early feature and scope behavior of for loops and comprehensions are identical.

---

<div class="post-metadata">

### Author: ![jballanc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jballanc/32/328_2.png) [@jballanc](https://discourse.julialang.org/u/jballanc)
#### Post date: [January 29, 2019, 1:27am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/186 "2019-01-29T01:27:04Z")

</div>

> [@PetrKryslUCSD](#):
>
> This code has not been tested, has it?

Well, no, considering there isn’t a `isprime` out of the box and I hadn’t had a chance to build Jeff’s branch yet…however now that I have, I can give an _actual_ example:

```julia
julia> contains_even = false
false

julia> start = 1
1
julia> finish = 1
1

julia> for i in start:finish
           if iseven(i)
               contains_even = true
           end
       end

julia> contains_even
false

julia> finish = 10
10

julia> for i in start:finish
           if iseven(i)
               contains_even = true
           end
       end

julia> contains_even
false

julia> for i in start:finish
           if iseven(i)
               contains_even |= true
           end
       end

julia> contains_even
true

julia> versioninfo()
Julia Version 1.2.0-DEV.219
Commit be8e29559d (2019-01-26 07:30 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin18.2.0)
  CPU: Intel(R) Core(TM) i5-5287U CPU @ 2.90GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.1 (ORCJIT, broadwell)

```

In this case, I’d prefer at least a warning that `contains_even` was being shadowed in the first version of the `for` loop.

---

<div class="post-metadata">

### Author: ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)
#### Post date: [January 29, 2019, 1:44am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/187 "2019-01-29T01:44:19Z")

</div>

Are you referring to this behavior in Python 2?

```python
$ python2
Python 2.7.15 (default, Jun 27 2018, 13:05:28)
[GCC 8.1.1 20180531] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> [x for x in range(3)]
[0, 1, 2]
>>> x
2

```

It actually got fixed in Python 3 (and also was not the case in the generator comprehension in Python 2 as well). OK, but I think you could say that Python 3 behavior is inconsistent in that the comprehension introduces a scope while the loop doesn’t, even though both of them use the keyword `for`. So, Python 3 is also sacrificing a part of consistency to get a tighter scope rule.

---

<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: [January 29, 2019, 1:57am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/188 "2019-01-29T01:57:28Z")

</div>

Yes, precisely.

---

<div class="post-metadata">

### Author: ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)
#### Post date: [January 29, 2019, 1:59am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/189 "2019-01-29T01:59:57Z")

</div>

@jballanc I’m interested in this so I dug up the history a little bit. It looks like a rule to make your example seem to be considered once (see the “write-only” case)

> [@StefanKarpinski](#):
>
> Another possible variation is that if every path is one of the following:
> 
> - read-before-write (including read-only)
> - write-only
> - no use
> 
> then the variable is global.

but it was rejected since simple insertion of `@show` etc. could change the behavior.

So the final version seems to be this one:

> [@StefanKarpinski](#):
>
> - if the first use of `x` on every path is a read, then `x` is global
> - if the first use of `x` on every path is a write and there’s a read somewhere, then `x` is local
> - otherwise `x` must have an explicit `local` or `global` annotation

But it seems in your second case (`finish = 10` with `contains_even = true` in the loop body) have to be caught by the third rule (i.e., has to be an error). Is this a bug in the PR?

---

<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: [January 29, 2019, 2:02am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/190 "2019-01-29T02:02:42Z")

</div>

Yes, I think that is actually a bug in the PR with respect to the specification I wrote.

Edit: I’ve commented as much on the PR.

---

<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: [January 29, 2019, 5:15am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/191 "2019-01-29T05:15:39Z")

</div>

> [@tkf](#):
>
> but it was rejected since simple insertion of `@show` etc. could change the behavior.

Doesn’t the revised proposal have a similar issue? For instance

```julia
for i = 1:10
    t = i
    @assert t>0
end

```

There `t` is local, but if you remove assertions then you get an error.

---

<div class="post-metadata">

### Author: ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)
#### Post date: [January 29, 2019, 6:43am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/192 "2019-01-29T06:43:41Z")

</div>

Hmm…, you are right. Also, isn’t this problematic as well?:

```diff
 t = "some important data"

 for i = 1:10
+ @assert t>0
     # many lines of code here
     t = i
     # many lines of code here
 end

 code_using_t(t)

```

i.e., by adding a read in the beginning of the `for` loop, you can modify the scope of `t` (which potentially break the following code). If you forget that `t` is a local variable (which may happen if the loop is long enough), I think this is a possible scenario.

---

<div class="post-metadata">

### Author: ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)
#### Post date: [January 29, 2019, 7:09am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/193 "2019-01-29T07:09:32Z")

</div>

It is exactly my point [above](https://discourse.julialang.org/t/new-scope-solution/16707/181).

One could also assume [possible future of @assert](https://github.com/JuliaLang/julia/pull/25576) (which I tried to demonstrate there with macro `@check`).

---

<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: [January 29, 2019, 7:11am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/194 "2019-01-29T07:11:37Z")

</div>

Linking back to the same post doesn’t help clarify anything.

---

<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: [January 29, 2019, 8:23am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/195 "2019-01-29T08:23:51Z")

</div>

> [@StefanKarpinski](#):
>
> But I also don’t want to answer questions from people being confused by accumulation not working in the REPL for the rest of my life.

I think it is inevitable that people coming to Julia will run into difficulties when applying concepts/habits learned in other programming languages. It is always nice to have fewer of these, but IMO this should _not_ be a primary design consideration.

It is my impression that people stumble into this _once_, grok it (because of #1—it _is_ simple), and move on. A _one-time cost_ is paid in exchange for a simpler set of rules for the _rest of their Julia experience_.

I appreciate the effort to come up with solutions for this problem, but frankly, all the proposed solutions have their own complications and we may be just trading one set of questions for another. If we stick with 1.0 scoping, I expect that eventually all the tutorials and texts on Julia will just contain a simple and polished explanation of it, making this a primarily pedagogical issue.

---

<div class="post-metadata">

### Author: ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)
#### Post date: [January 29, 2019, 11:27am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/196 "2019-01-29T11:27:36Z")

</div>

I am sorry discourse is not ideal platform. I was writing to @tkf . Means that he is trying to point same thing.

`@assert` (or `@check` in my example) could change meaning due to global state.

I would be surrprised, but in case you really miss it - my code “return” `16` in case `ENV["debug"]=="1"` and “return” `4` otherwise.

I was thinking it is clear counterexample to _“the meaning of code no longer depends on any global state—if you evaluate the same sequence of expressions in the REPL multiple times it means the same thing every time.”_

In case you knew it then sorry I don’t understand your question.

---

<div class="post-metadata">

### Author: ![Paul\_Soderlind](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paul_soderlind/32/1753_2.png) [@Paul\_Soderlind](https://discourse.julialang.org/u/Paul_Soderlind)
#### Post date: [January 29, 2019, 11:32am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/197 "2019-01-29T11:32:42Z")

</div>

Instead of changing the rules, would it be possible to introduce a macro

```julia
@behaveAsInFunction for t=1:10
...

```

?

Simple and transparent. Possible?

---

<div class="post-metadata">

### Author: ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)
#### Post date: [January 29, 2019, 11:54am UTC](https://discourse.julialang.org/t/new-scope-solution/16707/198 "2019-01-29T11:54:55Z")

</div>

> [@Tamas\_Papp](#):
>
> It is always nice to have fewer of these, but IMO this should _not_ be a primary design consideration.
> 
> It is my impression that people stumble into this _once_ , grok it (because of #1—it _is_ simple), and move on

_Really_ agree here. Especially for everyone worrying about teaching - this is just way simpler. You can always tell students “just add @global if it’s not in a function, I’ll explain why later,” or introduce the concept of scope (🥦) earlier, but this doesn’t add any weird gotchas.

I totally sympathize with Stefan not wanting to explain this the rest of his life but (a) I really don’t think it will last forever - this is part of the growing pain from 0.6 to 1 (and python to Julia) and (b) the fact you’re designing a programming language you’re planning to use for the rest of your life means you should do it right, not to satisfy the grumblers 😄

---

<div class="post-metadata">

### Author: ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)
#### Post date: [January 29, 2019, 2:44pm UTC](https://discourse.julialang.org/t/new-scope-solution/16707/199 "2019-01-29T14:44:08Z")

</div>

It will last forever since there will always be newcomers to the language. And regarding the “just write this and we discuss this later”: I absolutely do not like doing things like that in my programming courses. Julias strength is that it can hide a lot of the complexity from the introductory user.

Matlab is used worldwide is the goto language for teaching numerics (I know there are exceptions, but that are, well, exceptions). In that context, one usually will not talk about scope and the `global` requirement will scare people. I even don’t know if people teaching Matlab in numerics have heard about the term scope…

---

<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: [January 29, 2019, 2:55pm UTC](https://discourse.julialang.org/t/new-scope-solution/16707/200 "2019-01-29T14:55:27Z")

</div>

> [@tobias.knopp](#):
>
> I even don’t know if people teaching Matlab in numerics have heard about the term scope…

Judging from some of the Matlab code I have seen, the majority of Matlab programmers haven’t 😉

I think there is a more fundamental question implicit in these discussions: if

1. being easy to write _simple_ programs for people _new to programing_, and
2. being a powerful, consistent, and well-designed programming language for complex projects

are conflicting goals to some extent, do we resolve this in favor of (2) or (1)?

Eg _scope_ is a fundamental concept that people run inevitably run into for anything nontrivial. How much do we sacrifice of the language design just to avoid talking about it initially?

---

<div class="post-metadata">

### Author: ![jlperla](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlperla/32/34332_2.png) [@jlperla](https://discourse.julialang.org/u/jlperla)
#### Post date: [January 29, 2019, 3:05pm UTC](https://discourse.julialang.org/t/new-scope-solution/16707/201 "2019-01-29T15:05:36Z")

</div>

> [@Tamas\_Papp](#):
>
> Judging from some of the Matlab code I have seen, the majority of Matlab programmers haven’t

Exactly. And they are perfectly happy that way. This is not just intro users, but people using matlab for 2 decades… They never learned about scope because matlab has very intuitive scoping rules for scripts (and awful scoping rules for big projects).

> [@Tamas\_Papp](#):
>
> being a powerful, consistent, and well-designed programming language for complex projects

I am willing to bet that the overlap between people arguing to maintain the 1.0 behavior, and those actually affected by it is close to zero. Are you making a philosophical point, or talking about your own usage?

If you write code for a complex project or tonnes of code and packages, you could write a hundred thousand lines of code and never use the soft scope behavior, because it is only used by those hacking away at scripts and not advanced programmers.

Julia can fulfill both groups. The proposed changes to the 1.0 behavior has no impact on the “serious” scoping rules used in packages or big projects…where you would only design with a global after careful consideration and planning.

---

<div class="post-metadata">

### Author: ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)
#### Post date: [January 29, 2019, 3:13pm UTC](https://discourse.julialang.org/t/new-scope-solution/16707/202 "2019-01-29T15:13:36Z")

</div>

It could be cool. But could not macro bring complications for (future at least first versions of) debugger?

---

<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: [January 29, 2019, 3:13pm UTC](https://discourse.julialang.org/t/new-scope-solution/16707/203 "2019-01-29T15:13:48Z")

</div>

> [@jlperla](#):
>
> I am willing to bet that the overlap between people arguing to maintain the 1.0 behavior, and those actually affected by it is close to zero. Are you making a philosophical point, or talking about your own usage?

I am affected by it in the sense that I was very happy with the simplification of the rules in 1.0, and would be affected (in possibly minor ways, if I understand the recent proposals correctly, but I am still digesting the latest one) by a more complex rule.

> [@jlperla](#):
>
> never use the soft scope behavior, because it is only used by those hacking away at scripts and not advanced programmers

I hack away at scripts quite a bit (especially for data analysis). Writing complex packages and then working interactively with scripts are not exclusive activities; for most people the former are just for making the latter easier.

---

<div class="post-metadata">

### Author: ![yha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yha/32/3502_2.png) [@yha](https://discourse.julialang.org/u/yha)
#### Post date: [January 29, 2019, 3:36pm UTC](https://discourse.julialang.org/t/new-scope-solution/16707/204 "2019-01-29T15:36:42Z")

</div>

I would like to suggest yet another option: loops introduce a new scope _except_ when in global scope, i.e., giving up requirement #4 in top level. (Comprehensions always introduce a new scope.)

This does introduce a new difference between top-level behavior and behavior inside, which may seem to go against #3, but I think in practice the behavior would become more similar. For example, this currently works (and there seems to be a near-consensus that it should keep working):

```julia
function foo(r)
  found = false
  for x in r
    if istheone(x)
      found = true # writes to outer scope variable
    end
  end
end

```

This and similar patterns where a loop modifies variables from an enclosing scope would work similarly in global scope. So I think such behavior would improve the state of #3 from the perspective of prototyping use – writing block in top level and then moving them to functions would work in the common cases. This also removes problems as in the examples above where adding a seemingly innocuous read (such as in a `print` or `@assert`) changes the scope. So to me it seems to improve both #1 and #3 at the expense of #4 in top level.

The main difference that remains between top level and functions is that new variables introduced inside a loop in global scope would remain visible. This means that code which introduces new variables inside a loop and then reads them outside the loop would break when moved to a function. I think this is much less common, and therefore less harmful for the usual “prototyping” use case, but I might be missing some use case.  
I believe the main “production” use of loops in top level is for adding methods to functions inside loops, so presumably this use would not be affected.

[Previous page](https://discourse.julialang.org/t/new-scope-solution/16707.md?page=9)

[Next page](https://discourse.julialang.org/t/new-scope-solution/16707.md?page=11)
