Scope and constants

The region in the program where a variable is known is called the scope of that variable. Until now, we have only seen how to create top-level or global variables that are accessible from anywhere in the program. By contrast, variables defined in a local scope can only be used within that scope. A common example of a local scope is the code inside a function. Using global scope variables is not advisable for several reasons, notably the performance. If the value and type can change at any moment in the program, the compiler cannot optimize the code.

So, restricting the scope of a variable to local scope is better. This can be done by defining them within a function or a control construct, as we will see in the following chapters. This way, we can use the same variable name more than once without name conflicts.

Let's take a look at the following code fragment:

# code in chapter 2scope.jl 
x = 1.0 # x is Float64 
x = 1 # now x is Int 
y::Float64 = 1.0  
# ERROR: syntax: type declarations on global variables are not yet supported 
 
function scopetest() 
    println(x) # 1, x is known here, because it's in global scope 
    y::Float64 = 1.0  
# y must be Float64, this is not possible in global scope 
end 
 
scopetest() 
#> 1 
#> 1.0 
 
println(y) #> ERROR: UndefVarError: y not defined 

Variable x changes its type, which is allowed, but because it makes the code type unstable, it could be the source of a performance hit. From the definition of y in the third line, we can see that type annotations can only be used in local scope (here, in the scopetest() function).

Some code constructs introduce scope blocks. They support local variables. We have already mentioned functions, but for, while, try, let, and type blocks can all support a local scope. Any variable defined in a for, while, try, or let block will be local unless it is used by an enclosing scope before the block.

The following structure, called a compound expression, does not introduce a new scope. Several (preferably short) sub-expressions can be combined in one compound expression if you start it with begin, as in this example:

x = begin 
    a = 5 
    2 * a 
end # now x is 10 
println(a) #> a is 5  

After end, x has the value 10 and a is 5. This can also be written with ( ) as follows:

x = (a = 5; 2 * a)  #> 10 

The value of a compound expression is the value of the last sub-expression. Variables introduced in it are still known after the expression ends.

Values that don't change during program execution are constants, which are declared with const. In other words, they are immutable, and their type is inferred. It is a good practice to write their name in uppercase letters, like this:

const GC = 6.67e-11 # gravitational constant in m3/kg s2    

Julia defines a number of constants, such as ARGS (an array that contains the command-line arguments), VERSION (the version of Julia that is running), and OS_NAME (the name of the operating system such as Linux, Windows, or Darwin), mathematical constants (such as pi and e), and Datetime constants (such as Friday, Fri, August, and Aug).

If you try to give a global constant a new value, you get a warning, but if you change its type, you get an error, as follows:

julia> GC = 3.14 
      Warning: redefining constant GC 
julia> GC = 10 
      ERROR: invalid redefinition of constant GC 
Constants can only be assigned a value once, and their type cannot change, so they can be optimized. Use them whenever possible in the global scope.

So, global constants are more about type than value, which makes sense, because Julia gets its speed from knowing the correct types. If, however, the constant variable is of a mutable type (for example, Array, Dict (refer to Chapter 8, I/O, Networking, and Parallel Computing)), then you can't change it to a different array, but you can always change the contents of that variable:

julia> const ARR = [4,7,1] 
julia> ARR[1] = 9 
julia> show(ARR) #> [9,7,1] 
julia> ARR = [1, 2, 3] 
  Warning: redefining constant ARR 

To review what we have learned in this chapter, we will play with characters, strings, and arrays in the following program (strings_arrays.jl):

using Statistics 
# a newspaper headline: 
str = "The Gold and Blue Loses a Bit of Its Luster" 
println(str) 
nchars = length(str) 
println("The headline counts $nchars characters") # 43 
str2 = replace(str, "Blue" => "Red") 
 
# strings are immutable 
println(str) # The Gold and Blue Loses a Bit of Its Luster 
println(str2) 
println("Here are the characters at position 25 to 30:") 
subs = str[25:30] 
print("-$(lowercase(subs))-") # "-a bit -" 
println("Here are all the characters:") 
for c in str 
    println(c) 
end 
arr = split(str,' ') 
show(arr) 
#["The","Gold","and","Blue","Loses","a","Bit","of","Its","Luster"] nwords = length(arr) println("The headline counts $nwords words") # 10 println("Here are all the words:") for word in arr println(word) end arr[4] = "Red" show(arr) # arrays are mutable println("Convert back to a sentence:") nstr = join(arr, ' ') println(nstr) # The Gold and Red Loses a Bit of Its Luster # working with arrays: println("arrays: calculate sum, mean and standard deviation ") arr = collect(1:100) typeof(arr) #> Array{Int64,1} println(sum(arr)) #> 5050 println(mean(arr)) #> 50.5
..................Content has been hidden....................

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