Scope revisited

A variable that is defined at the top level is said to have global scope.

The for, while, and try blocks (but not the if blocks) all introduce a new scope. Variables defined in these blocks are only known to that scope. This is called the local scope, and nested blocks can introduce several levels of local scope. However, global variables are not accessible in for and while loops.

Variables with the same name in different scopes can safely be used simultaneously. If a variable exists both in global and local scope, you can decide which one you want to use by prefixing them with the global or local keyword:

  • global: This indicates that you want to use the variable from the outer, global scope. This applies to the whole of the current scope block.
  • local: This means that you want to define a new variable in the current scope.

The following example will clarify this, as follows:

# code in Chapter 4scope.jl 
x = 9  
function funscope(n) 
  x = 0 # x is in the local scope of the function 
  for i = 1:n 
    local x # x is local to the for loop 
    x = i + 1 
    if (x == 7) 
        println("This is the local x in for: $x") #=> 7 
    end 
  end 
  x 
  println("This is the local x in funscope: $x") #=> 0 
  global x = 15 
end 
 
funscope(10) 
println("This is the global x: $x") #=> 15 

This prints out the following result:

This is the local x in for: 7 
This is the local x in funscope: 0 
This is the global x: 15 

If the local keyword was omitted from the for loop, the second print statement would print out 11 instead of 7, as follows:

This is the local x in for: 7 
This is the local x in funscope: 11 
This is the global x: 15 

What is the output when the global x = 15 statement is left out? In this situation, the program prints out this result:

This is the local x in for: 7 
This is the local x in funscope: 11 
This is the global x: 9

However, needless to say, such name conflicts obscure the code and are a source of bugs, so try to avoid them if possible.

If you need to create a new local binding for a variable, use the let block. Execute the following code snippet:

anon = Array{Any}(undef, 2)  
for i = 1:2 
  anon[i] = ()-> println(i) 
  i += 1 
end 

Here, both anon[1] and anon[2] are anonymous functions. When they are called with anon[1]() and anon[2](), they print 2 and 3 (the values of i when they were created plus one). What if you wanted them to stick with the value of i at the moment of their creation? Then, you have to use let and change the code to the following:

anon = Array{Any}(undef, 2) 
for i = 1:2 
  let i = i 
      anon[i] = ()-> println(i)  
  end 
  i += 1 
end 

Now, anon[1]() and anon[2]() print 1 and 2, respectively. Because of let, they kept the value of i the same as when they were created.

The let statement also introduces a new scope. You can, for example, combine it with begin, like this:

begin 
    local x = 1 
    let 
       local x = 2 
       println(x) #> 2 
    end 
    x 
    println(x) #> 1 
end

for loops and comprehensions differ in the way they scope an iteration variable. When i is initialized to 0 before a for loop, after executing for i = 1:10 end, the variable i is now 10:

i = 0 
for i = 1:10 
end 
println(i)  #> 10 

After executing a comprehension such as [i for i = 1:10], the variable i is still 0:

i = 0 
[i for i = 1:10 ] 
println(i)  #> 0 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.239.103