3
for i in 1:2
    if i == 2
        print(x)
    end
    if i == 1
        x = 0
    end
end

UndefVarError : x not defined

Why does the code gives that error instead of printing 0 in julia?

While in python the following code print 0?

for i in range(2):
    if i==1:
        print(x)
    if i==0:
        x=0
niczky12
  • 4,953
  • 1
  • 24
  • 34
Erik Garcia
  • 88
  • 1
  • 6
  • No language will let you use a variable *before* you declare it. And `x` is undeclared. –  Jun 18 '18 at 15:29
  • the variable is not used before declaring it and this works in python – Erik Garcia Jun 18 '18 at 15:35
  • You're using it on line 3. Where are you declaring it? And no, this won't work in Python. Please open a Python prompt and type in `print(x)`. You'll get `NameError: name 'x' is not defined` –  Jun 18 '18 at 15:36
  • 3
    @Amy: this actually _will_ work in Python, because `x` is set to 0 on the first iteration of the loop and only printed on the second. – DSM Jun 18 '18 at 15:48
  • in python x is not defined in the first iteration, it is defined in the second one. And yes this works in python. – Erik Garcia Jun 18 '18 at 15:52
  • 1
    Julia has local scoping introduced by most code blocks. This is so that the compiler can optimise the functions easily. Check out this in the docs: https://docs.julialang.org/en/v0.6.2/manual/variables-and-scoping/#Local-Scope-1 – niczky12 Jun 18 '18 at 15:57

2 Answers2

4

The reason is because in the loop a variable gets a new binding each time a loop is executed, see https://docs.julialang.org/en/latest/manual/variables-and-scoping/#For-Loops-and-Comprehensions-1.

In fact while loop changed this behavior between Julia 0.6.3 and Julia 0.7 (in Julia 0.6.3 a new binding was not created). Therefore the following code:

function f()
    i=0
    while i < 2
        i+=1
        if i == 2
            print(x)
        end
        if i == 1
            x = 0
        end
    end
end

Gives the following output.

Julia 0.6.3

julia> function f()
           i=0
           while i < 2
               i+=1
               if i == 2
                   print(x)
               end
               if i == 1
                   x = 0
               end
           end
       end
f (generic function with 1 method)

julia> f()
0

Julia 0.7.0

julia> function f()
           i=0
           while i < 2
               i+=1
               if i == 2
                   print(x)
               end
               if i == 1
                   x = 0
               end
           end
       end
f (generic function with 1 method)

julia> f()
ERROR: UndefVarError: x not defined
Stacktrace:
 [1] f() at .\REPL[2]:6
 [2] top-level scope

For-loop created a new binding already in Julia 0.6.3 at each iteration so it fails both under Julia 0.6.3 and Julia 0.7.0.

EDIT: I have wrapped the examples in a function, but you would get the same result if you executed the while loop in global scope.

Bogumił Kamiński
  • 66,844
  • 3
  • 80
  • 107
2

Ignore my comment andgo with Bogumil's answer as that's is the real rwason why your x variable disapears in thesecond iteration.

If you want your code to work like in Python, you can add the global keyword to your assignment of x:

for i in 1:2
    if i == 2
        print(x)
    end
    if i == 1
        global x = 0
    end
end

Note that this is not recommended in most cases as it'll make your code performance suffer. Julia likes local variables that the compiler can optimise away easily.

niczky12
  • 4,953
  • 1
  • 24
  • 34
  • The reason is not local scoping but rebinding of a variable in a `for` loop. See the explanation in my answer. Additionally `if` block does not introduce a new scope as is explained in https://docs.julialang.org/en/latest/manual/variables-and-scoping/#scope-of-variables-1. – Bogumił Kamiński Jun 18 '18 at 16:13
  • You are right. Sorry I mixed things up a bit. I changed my answer to reflect this. – niczky12 Jun 18 '18 at 17:36