Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scope of Julia variable with if block nested in for loop

Tags:

julia

for i=1:5
    if(i==1)
        z = i
    end
    println("i = $i, z = $z")
end

i = 1, z = 1
ERROR: UndefVarError: z not defined
Stacktrace:
 [1] top-level scope at ./REPL[6]:5 [inlined]
 [2] top-level scope at ./none:0

The behavior of the above script is puzzling to me. Can someone help me understand why the print works when i=1 but fails when i=2.

like image 352
Rohan Fernando Avatar asked Feb 28 '19 16:02

Rohan Fernando


People also ask

What is global variable in Julia?

'global' keyword in Julia is used to access a variable that is defined in the global scope. It makes the variable where it is used as its current scope and refers to the global variable of that name.

What does Const do Julia?

When you declare a variable as const , you are just telling something about how that name shall be used. So, it doesn't matter what content you assign to var2 the first time. If you don't declare it as const , there is nothing stopping you from assigning it a different value – maybe of a different type – later on.

How do you declare a variable in Julia?

Variables in Julia can be declared by just writing their name. There's no need to define a datatype with it. Initializing variables can be done at the time of declaring variables. This can be done by simply assigning a value to the named variable.

What is let in Julia?

Let Blockslet statements create a new hard scope block (see above) and introduce new variable bindings each time they run. The variable need not be immediately assigned: julia> var1 = let x for i in 1:5 (i == 4) && (x = i; break) end x end 4.


2 Answers

The answer by @Wookies-Will-Code is correct and here is the reason.

As the Julia manual explains here:

for loops, while loops, and Comprehensions have the following behavior: any new variables introduced in their body scopes are freshly allocated for each loop iteration

Which means that at the end each iteration z is forgotten.

In order to make sure the value of z is persistent across iterations (and also after for loop finishes) define z before the loop. For example like this:

function mytest()
    local z
    for i=1:5
        if i==1
            z = i
        end
        println("i = $i, z = $z")
    end
end

and now you have:

julia> mytest()
i = 1, z = 1
i = 2, z = 1
i = 3, z = 1
i = 4, z = 1
i = 5, z = 1

Observe that the situation is different in global scope. Even if z is globally defined it is not reused by default:

julia> z = 100
100

julia> for i=1:5
           if i==1
               z = i
           end
           println("i = $i, z = $z")
       end
i = 1, z = 1
ERROR: UndefVarError: z not defined
Stacktrace:
 [1] top-level scope at .\REPL[7]:5 [inlined]
 [2] top-level scope at .\none:0

The reason is that Julia treats z as local to the for loop, because z is assigned to inside the loop. This is a compile time feature check so even if the if condition always fails you will get this error:

julia> z = 100
100

julia> for i=1:5
           if false
               z = i
           end
           println("i = $i, z = $z")
       end
ERROR: UndefVarError: z not defined
Stacktrace:
 [1] top-level scope at .\REPL[18]:5 [inlined]
 [2] top-level scope at .\none:0

You have to assign to z using global keyword to make it work:

julia> z = 100
100

julia> for i=1:5
           if i==1
               global z = i
           end
           println("i = $i, z = $z")
       end
i = 1, z = 1
i = 2, z = 1
i = 3, z = 1
i = 4, z = 1
i = 5, z = 1
like image 169
Bogumił Kamiński Avatar answered Oct 10 '22 21:10

Bogumił Kamiński


I do not use Julia, but here goes. I am not sure how to send the string that z is not defined, but here 2 different prinln based on the value of i, simplest way to do it, or else you have to check if z is defined, this is simpler.

for i=1:5
    if(i==1)
        z = i
        println("i = $i, z = $z")
    else
        println("i = $i","z not defined")
    end
end
like image 29
Wookies-Will-Code Avatar answered Oct 10 '22 21:10

Wookies-Will-Code