Global scope confusion again

This code runs in JuliaBox (0.6.4), but running the code in JuliaPro on OSX Mojave the same code (cut and pasted) returns an error message (undefined variable a). I have the same problem both on my MacMini and my MacBook Pro. Both of them are running Mojave and Julia 1.0.2.

a=1.0
b=1.0
e=0.1
for i in 1:5
x=a-eb
y=b+e
a
println(i," “,x,” ",y
a=x
b=y
end

a is a global variable in the REPL and must be annotated inside the loop as such, to avoid this, insert your code inside a function. See this discussion for more information: REPL and for loops (scope behavior change).

julia> function test()
           a = 1.0
           b = 1.0
           e = 0.1
           for i in 1:5
               x = a - e*b
               y = b + e*a
               println(i," “,x,” ",y)
               a = x
               b = y
           end
       end
test (generic function with 1 method)

julia> test()
1 “,x,” 1.1
2 “,x,” 1.1900000000000002
3 “,x,” 1.2690000000000001
4 “,x,” 1.3361
5 “,x,” 1.3905100000000001

Yes, indeed. Thank you :grinning:

I generally try not to write code that will run in the top-level scope, but rather lives in functions.
That simplifies the scope considerations. And, as a side effect, makes it much less likely that unintended interactions between unrelated variables occur.

6 Likes

Sometimes people like to explore interactively, and that’s okay too.

3 Likes

That sounds good (I don’t really understand it), but I’d love to see how that would actually work with the loop I had in mind.

This works:

function f()
a=1.0
b=1.0
e=0.1
for i in 1:5
	x=a-e * b
	y=b+e * a
	println(i," “,x,” ",y)
	a=x
	b=y
end
end

Yes, and if you do that trick twice in a row, it no longer works in my Julia 1.x:

LoadError: cannot define function g; it already has a value
in expression starting at untitled-89a579f7bc9ac012ee08ef9568e08477:13
top-level scope at none:0

function f()
a=1.0
b=1.0
e=0.1
for i in 1:5
x=a-e * b
y=b+e * a
println(i," “,x,” ",y)
a=x
b=y
end
end

function g()
a=1.0
b=1.0
e=0.1
for i in 1:5
x=a-e * b
y=b+e * a
println(i," “,x,” ",y)
a=x
b=y
end
end

The point is that one can indeed make anything work, given enough perseverance, but I specifically got into Julia because that is not something I want to spend my time on, if I can avoid it. Julia was supposed to be an intuitive beautiful language for technical people who want performance and a reasonable aesthetic. Julia 0.x. was that for me.

I’m sure there’s a great explanation for why the above code doesn’t work, but the explanation does not make my present state of alienation from Julia go away.

You possibly defined a constant g, this is unrelated.

Sorry, I don’t follow. If I take the definition of the function and paste it repeatedly into the REPL, the function is defined and redefined over and over without any problems. What is the context of your difficulty? Did you start from fresh, or did you have already things defined and running? Do tell us a little bit more.

This is the problem: I run the same code twice in a row in a single program. First as f() and then as g(). I get this error code:

LoadError: cannot define function g ; it already has a value
in expression starting at untitled-89a579f7bc9ac012ee08ef9568e08477:13
top-level scope at none:0

julia> function f()                                                                                            
       a=1.0                                                                                                   
       b=1.0                                                                                                   
       e=0.1                                                                                                   
       for i in 1:5                                                                                            
           x=a-e * b                                                                                           
               y=b+e * a                                                                                       
                   println(i," “,x,” ",y)                                                                      
                       a=x                                                                                     
                           b=y                                                                                 
                           end                                                                                 
                           end                                                                                 
f (generic function with 1 method)                                                                             
                                                                                                               
julia> function f()                                                                                            
       a=1.0                                                                                                   
       b=1.0                                                                                                   
       e=0.1                                                                                                   
       for i in 1:5                                                                                            
           x=a-e * b                                                                                           
               y=b+e * a                                                                                       
                   println(i," “,x,” ",y)                                                                      
                       a=x                                                                                     
                           b=y                                                                                 
                           end                                                                                 
                           end                                                                                 
f (generic function with 1 method)                                                                             
                                                                                                               
julia> function f()                                                                                            
       a=1.0                                                                                                   
       b=1.0                                                                                                   
       e=0.1                                                                                                   
       for i in 1:5                                                                                            
           x=a-e * b                                                                                           
               y=b+e * a                                                                                       
                   println(i," “,x,” ",y)                                                                      
                       a=x                                                                                     
                           b=y                                                                                 
                           end                                                                                 
                           end                                                                                 
f (generic function with 1 method)                                                                             
                                                                                                               
julia> function f()                                                                                            
       a=1.0                                                                                                   
       b=1.0                                                                                                   
       e=0.1                                                                                                   
       for i in 1:5                                                                                            
           x=a-e * b                                                                                           
               y=b+e * a                                                                                       
                   println(i," “,x,” ",y)                                                                      
                       a=x                                                                                     
                           b=y                                                                                 
                           end                                                                                 
                           end                                                                                 
f (generic function with 1 method)                                                                             
                                                                                                               
julia> function g()                                                                                            
       a=1.0                                                                                                   
       b=1.0                                                                                                   
       e=0.1                                                                                                   
       for i in 1:5                                                                                            
           x=a-e * b                                                                                           
               y=b+e * a                                                                                       
                   println(i," “,x,” ",y)                                                                      
                       a=x                                                                                     
                           b=y                                                                                 
                           end                                                                                 
                           end                                                                                 
g (generic function with 1 method)                                                                             
                                                                                                               
julia> function f()                                                                                            
       a=1.0                                                                                                   
       b=1.0                                                                                                   
       e=0.1                                                                                                   
       for i in 1:5                                                                                            
           x=a-e * b                                                                                           
               y=b+e * a                                                                                       
                   println(i," “,x,” ",y)                                                                      
                       a=x                                                                                     
                           b=y                                                                                 
                           end                                                                                 
                           end                                                                                 
f (generic function with 1 method)                                                                             
                                                                                                               
julia>                                                                                                         
                                                                                                               
julia> function g()                                                                                            
       a=1.0                                                                                                   
       b=1.0                                                                                                   
       e=0.1                                                                                                   
       for i in 1:5                                                                                            
           x=a-e * b                                                                                           
               y=b+e * a                                                                                       
                   println(i," “,x,” ",y)                                                                      
                       a=x                                                                                     
                           b=y                                                                                 
                           end                                                                                 
                           end                                                                                 
g (generic function with 1 method)                                                                             
                                                                                                               
julia> versioninfo()                                                                                           
Julia Version 1.1.0-DEV.509                                                                                    
Commit 1db6047018 (2018-10-21 02:53 UTC)                                                                       
Platform Info:                                                                                                 
  OS: Linux (x86_64-pc-linux-gnu)                                                                              
  CPU: Intel(R) Core(TM) i7-6650U CPU @ 2.20GHz                                                                
  WORD_SIZE: 64                                                                                                
  LIBM: libopenlibm                                                                                            
  LLVM: libLLVM-6.0.1 (ORCJIT, skylake)      

No problem.

1 Like

It appears that we have a discrepancy between how our machines behave. I have Julia version 1.0.2. running on Juno. I tried what you did and it does not work on my machine. I first ran f() and g() in the same program just like I did before. No go. Then, I ran f() and g() one by one in the REPL. No go. It throws the same error message concerning g() already having a value. Then I ran f() and g() as a single program in REPL and still no go.

Or, possibly, you are ignoring suggestions or questions that could help you solve the problem, ie

1 Like

An alternative way to debug this is to see what g is in your current session.

1 Like

:+1:Thank you guys so much for trying to help me with this. As long as I was running 0.x in Juno, I was in heaven and the books I had on Julia made things comprehensible. I think that I’m now way over my head and in the wrong world with this scoping thing because I can’t seem to conceptualize scoping properly. It seems like a genuine computer science thing, which real programmers deal with gracefully.

I think that I need to bite the bullet and start using Mathematica. It’s a shame, because Julia 0.x had a virtually zero learning curve for me, and that was truly amazing! Only Basic and Fortran have given me zero learning curves in the past, but they belong to the past millennium.

Having said that, I don’t want this to reflect badly on Julia. I just want to debug my own thinking rather than somebody else’s product.

That seems like a bit of an overreaction to a single language change. The rule is very simple: if you want to modify a global variable inside of any scope-creating construct (loops, functions, let) you need to use the global keyword. Without that, an assignment inside any scope-creating construct assigns to a local variable if one already exists, or declares a new one if none exists; in no case does it assign to a global without the global annotation. Is writing global occasionally really so taxing that it’s easier to change programming languages entirely?

Aside: Mathematica is a wonderful system but it has super broken scope behavior.

11 Likes

If I were to guess the broader point: the mental model of scoping he has in mind (that I can take almost any code and put a function around it, like you could do in v0.6) is broken, and he thinks that the new scoping rules are sufficiently perplexing that it is a signal of what else is counter-intuitive and possibly “buggy” in the language. It is not just about “writing global” occasionally, but about the inability to copy/paste code, reorganize in functions, etc. without thinking through scoping rules. This didn’t happen before, and doesn’t happen currently with jupyter. As you know, there are a lot of other people who agree with him that this is bad enough to be called “a bug”, however intentional it may have been.

But, I also think that this is an overreaction to this particular problem. The solution is simple, and it is what everyone I know dealing with introductory users is telling people:

  1. Never, under any circumstances, use loops etc. in the REPL or in a script, unless wrapped in a function. Period.
  2. If you want to do interactive work, for now you should generally use Jupyter which fixed this “bug” (of course, not really a bug in that it was intentional) with something called SoftGlobalScope, leading to the behavior of before.

If you follow this rule, you will never hit this problem. If I was to guess, the reason we don’t run into this more often is because (1) those teaching beginners always tell people to stick in jupyter, and (2) anyone who is not a beginner is already organizing code in functions.

@StefanKarpinski are there any updates on the timing of the https://discourse.julialang.org/t/another-possible-solution-to-the-global-scope-debacle/ solution?

1 Like

The problem you are facing now has nothing to do with the new scope behaviour.
As others pointed out, you must have defined previously the variable g, then probably forgot about that, and because g is a variable name you cannot create a function with the same name.
It doesn’t work in v0.6 either:

julia> g = "Hi"
"Hi"

julia> function g()
       println("Hello")
       end
ERROR: cannot define function g; it already has a value

julia> versioninfo()
Julia Version 0.6.4
Commit 9d11f62bcb (2018-07-09 19:09 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin14.5.0)
  CPU: Intel(R) Core(TM) i5-5287U CPU @ 2.90GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell MAX_THREADS=16)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, broadwell)

4 Likes

Yeah, that’s why I asked what value g already had.

1 Like