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?
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.
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.
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.
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?
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:
1 <=== CONFUSING TO BEGINNERS/Matlab
since they would probably expect the iteration variable “x” to also be global. so should print out:
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
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.
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
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.
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
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.
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.
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
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: 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
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??
Does that mean that any loop outside of a function, e.g. in the REPL, will become slow? Or was that the case already?
These syntax choices are not relevant to performance. Defaulting to local or global in certain syntactic situations does not have any effect on the performance of locals or globals, only on how you express what you want to do. This is like suggesting that if we talk about horses in German they might run faster. The way you explain which horse you want to bet on has no effect on how fast it runs.
As someone who teaches matlab users, I disagree. The “local loop index” behavior is something worth teaching people, as it makes plenty of sense and is consistent with scoping in the rest of the language. Matlab has many charms, but sane scoping rules are not one of them.