Another possible solution to the global scope debacle

No, very much intentional:

1 Like

Is there so to speak a “right” solution, irrespective of cost or impact on the user community?

1 Like

Yes, adding a way to opt-in to the future behavior makes sense.

But it’s not that or having a deprecation strategy for changing the default—that’s something to have in addition to that.

That’s what we’re trying to determine. The proposal here is the best we’ve come up with, which we’re proposing to get feedback. At this point, we’re quite certain that there is no technically ideal solution to this problem. We’ve explored the problem space very thoroughly. Of course, it’s possible we missed something, but at this point it’s a bit unlikely.

module Module
    const CONST = 1 # not exported
end

using Module
# CONST is not global here, right?
# only Module.CONST would get at it, right?
1 Like

Correct.

Personally, I would prefer a less radical way and just have the deprecation warning for 1.1 and 1.2 (or maybe even longer) instead of throwing an error in 1.2.
Since the time span between the 1.1 release and the 1.3 release is probably quite a few months apart, it would give users enough time to fix the warning.

2 Likes

From practical experience, we’ve learned that people simply ignore warnings. Also, please, let’s focus on the actual final state we want to get to, not how to get there. That’s a secondary question. The main question is whether the scoping rules described here are the ones we want.

6 Likes

Responding to the original post, I think Jeff’s proposed semantics are reasonable.

If we make these semantics apply to the REPL in 1.1 and be opt-in otherwise (e.g. for IJulia or for scripts that want this behavior), that would satisfy most of my concerns about usability and pedagogy.

16 Likes

Yes, that would be a great compromise between getting a fix out fast for the confused newbies while still respecting the no breaking changes policy.

I freaked out a bit after interpreting Stefan’s 1.1-1.2-1.3 post above as meaning that the REPL could possibly have usability issues for the next ~9 months. But if the REPL is patched in 1.1 I’m all aboard.

I for one would prefer to have to declare variables defined outside of the scope of the function as global in order to use them inside. That seems much safer.

On the other hand, I am fine with modifying variables outside of the scope of for loops and if-blocks that are defined above these local scopes.

Any chance this might be considered? Any drawbacks in your opinion?

1 Like

I think matlab beginners will still be confused unless the for loop iteration variable is also global.

I think I understand the current proposal.

this code currently produces an error in the REPL, which is very confusing to beginners.


i = 10
x = 1
for x = 1:3
    i = i + 1
    print(i,"\n")
    print(x,"\n")
end
print(i,"\n")
print(x,"\n")

the current proposal would make global the default:


global i = 10
global x = 1
for x = 1:3
    global i = i + 1
    print(i,"\n")
    print(x,"\n")
end
print(i,"\n")
print(x,"\n")

which prints out in the REPL:

julia> include(“glob.jl”)
11
1
12
2
13
3
13
1 <=== CONFUSING TO BEGINNERS/Matlab

since they would probably expect the iteration variable “x” to also be global. so should print out:

julia> include(“glob.jl”)
11
1
12
2
13
3
13
3 <=== what beginners/matlab would expect (i.e there is only one “x”, and its global…)

but neither this code block

global i = 10
global x = 1
for global x = 1:3  ## HOW TO MAKE X global again??? 
    global i = i + 1
    print(i,"\n")
    print(x,"\n")
end
print(i,"\n")
print(x,"\n")

nor this block


global i = 10
global x = 1
for outer x = 1:3  ## how to refer to global x??? 
    global i = i + 1
    print(i,"\n")
    print(x,"\n")
end
print(i,"\n")
print(x,"\n")

works in 1.0.1.

So to be consistent, I think in the REPL and outside of functions ALL variables should be global?

or am I missing something.

hope this at least did not distract from conversation

1 Like

Could you give an example? I’m not sure what you mean. I think you’re referring to needing extra declarations to be able to read global variables from inside a function. If so, then that would be a separate breaking change from this one, and it seems much too strict to me. But I may be misunderstanding.

This is not on the table. We changed that behavior many versions ago and have received zero complaints.

4 Likes

Even if I write let x = 0; ...; end, x will be global? Doesn’t seem like a good idea. There is also a significant amount of code that uses let or local declarations at the top level, and there’s no need to break it.

I agree we can add for global i = ... and for outer i = ... (for globals); those are currently errors so can be added as a new feature.

I think top-level for loop iteration variables should be as similar as possible to those inside functions. Global loop counters seem fairly insane to me.

6 Likes

Aye, that is what I meant. I have used variables defined in functions in nested subfunctions often enough. Convenient, yes, but dangerous too. I have been often bitten by subtle bugs caused by this design.

It would be quite nice to have to say

x = 1
function f(y)
    global x
    return x+y
end

in order to have access to x.

3 Likes

Unfortunately, top-level functions are also named by global variables, so you’d need global + as well. So I think that is unworkable. Even if we had some kind of exception for functions, this would be a hugely breaking change and it’s fairly separate from the present issue.

5 Likes

Sorry for just wild ideas here!

What about impact to performance?

I am thinking about another infamous feature of REPL - bad performance in global scope.

If for is hard scoped now in REPL does that mean that it is/could be quick as compiled function?

Couldn’t we trying to solve REPL slowness too?

Maybe we could have something like this to avoid globals in for block?

x = 1
for(x=x) i in 1:10  # x is parameter
   x += i  # x is local here
end(x=x)  # means:  outer x = local x  

couldn’t be easier to explain (not only) to newbies why simple copy+paste doesn’t work, if someone would have possibility to simply fix it and could gain better performance?

Error message ERROR: UndefVarError: x not defined could be change to something like ERROR: UndefVarError: x not defined (don't you want to parametrize for? see http://docs.julialang.org/explanation)

another variant (maybe more julian way?)

x = 1
for x=x, i in 1:10  # x is parameter
   x += i  # x is local here
do 
  x=x  # means:  outer x = local x
end

Maybe I am wrong but I think that this could be add independently to Jeff’s proposal. It could bring back possibility to remove globals from for block in REPL and keep possibility to change global variables.

Although something like this could be problem:

x = 1
function f() global x=x+x end  # this is not very julian but supported
for x=x, i in 1:10  # x is parameter
   x += i  # x is local here
   f()  # PROBLEM local x is ignored (maybe outer in f could help?)
do 
  x=x  # means:  outer x = local x
end
1 Like

Since we are talking about absolute matlab beginners, they will not know about “let” or “local” yet anyway, so I’m not suggesting changing anything even moderately “advanced” from a CS standpoint. Of course global loop iterators are not a good idea, but we are talking about beginners But perhaps it is better to enforce some good programming conventions on beginners, and so I’m 100% fine with keeping for loop variables local, especially now that I think I finally understand what the global/local scoping transition debate is all about

perhaps for pedantic reasons it would be nice for this to be a no-op --, as a reminder to beginners that the iteration variables are in fact local (different) and thus why print(x) is different inside and outside the for loop.

for local x = 1:3 .... ## no-op for pedantic purposes??