Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

The scope of the Julia variable


May 14, 2021 Julia


Table of contents


The scope of the variable

The scope of a variable is the area where the variable is visible. Variable scopes can help avoid variable naming conflicts.

A scope block is a region of code that is the scope of a variable. T he scope of the variables is limited to the inside of these blocks. Scope blocks are:

  • function body (or syntax)
  • while loop body
  • for loop body
  • try block
  • catch block
  • let block
  • type block

Note that the begin block cannot introduce a new scope block.

When a variable is introduced into a scope, all internal scopes inherit the variable unless an internal scope explicitly copies it. Ways to introduce new variables into the current scope:

  • Declare local x const x introduce new local variables
  • Declaring global x causes x to introduce the current scope and the innerer scope
  • The argument of the function, which is introduced into the scope of the function body as a new variable
  • Whether before or after the current x = y x x a global variable or introduced as a local variable in any outer scope

In the following example, inside and outside the loop, only one x assigned:

function foo(n)
  x = 0
  for i = 1:n
    x = x + 1
  end
  x
end

julia> foo(10)
10

In the following example, the loop body has a separate x and the function always returns 0:

function foo(n)
  x = 0
  for i = 1:n
    local x
    x = i
  end
  x
end

julia> foo(10)
0

In the following example, x inside the loop body, so the function encounters an undefined error on the last line x has been declared a global variable):

function foo(n)
  for i = 1:n
    x = i
  end
  x
end

julia> foo(10)
in foo: x not defined

The only way to assign value to a global variable in a non-top scope is to explicitly declare that the variable is global in a scope. Otherwise, assignments introduce new local variables instead of assigning values to global variables.

You don't have to introduce x on an external assignment before you use x

function foo(n)
  f = y -> n + x + y
  x = 1
  f(2)
end

julia> foo(10)
13

The example above may seem strange, but it's no problem. B ecause here is a function bound to a variable. T his allows us to define functions in any order without having to declare them from the bottom up or in advance like C. Here's an inefficient example of recursively validating a positive parity:

even(n) = n == 0 ? true  :  odd(n-1)
odd(n)  = n == 0 ? false : even(n-1)

julia> even(3)
false

julia> odd(3)
true

Julia has built-in iseven isodd to verify parity.

Because functions can be called and then defined, there is no need to declare in advance, and the order of definitions can be arbitrary.

In interactive mode, you can hypothesically have a layer of scope block packages outside of any input, similar to global scopes:

julia> for i = 1:1; y = 10; end

julia> y
ERROR: y not defined

julia> y = 0
0

julia> for i = 1:1; y = 10; end

julia> y

10

In the previous example, y only for loop. I n the latest example, the externally y is introduced into the loop. B ecause the scope of the session is similar to the global scope, you do not have to declare global y However, code that does not run in interactive mode must declare a global variable.

Multivariables can be declared global using the following syntax:

function foo()
    global x=1, y="bar", z=3
end

julia> foo()
3

julia> x
1

julia> y
"bar"

julia> z
3

let statement provides another way to introduce variables. let statement declares a new variable each time it runs. let syntax accepts assignment statements or variable names separated by commas:

let var1 = value1, var2, var3 = value3
    code
end

let x = x syntax because the two x are different. I t first values the right side, then introduces a new variable on the left and assigns a value. Here's an example of what you need to do with let

Fs = cell(2)
i = 1
while i <= 2
  Fs[i] = ()->i
  i += 1
end

julia> Fs[1]()
3

julia> Fs[2]()
3

The return values of the two closures are the same. If you let variable i with i

Fs = cell(2)
i = 1
while i <= 2
  let i = i
    Fs[i] = ()->i
  end
  i += 1
end

julia> Fs[1]()
1

julia> Fs[2]()
2

Because begin block does not introduce new scope blocks, it is useful to use let to introduce new scope blocks:

julia> begin
         local x = 1
         begin
           local x = 2
         end
         x
       end
ERROR: syntax: local "x" declared twice

julia> begin
         local x = 1
         let
           local x = 2
         end
         x
       end
1

The first example is that a local variable with the same name cannot be declared in the same scope. In the second example, let introduces a new scope block, where the local variable x from the local variable x of the x layer.

For Loops and Comprehensions

For loops and Comprehensions have special behavior: the new variables declared in them are re-declared in each loop. Therefore, it is a bit like a let with an while block:

Fs = cell(2)
for i = 1:2
    Fs[i] = ()->i
end

julia> Fs[1]()
1

julia> Fs[2]()
2

for loop iterates with variables that already exist:

i = 0
for i = 1:3
end
i  # here equal to 3

However, comprehensions, in contrast, always declares new variables:

x = 0
[ x for x=1:3 ]
x  # here still equal to 0

Constant

const keyword tells the compiler to declare a constant:

const e  = 2.71828182845904523536
const pi = 3.14159265358979323846

const can declare global and local constants, preferably using it to declare global constants. T he value (or even type) of a global variable can change at any time, and it is difficult for the compiler to optimize it. If the global variables do not change, you can add a const to resolve performance issues.

Local variables are different. The compiler can automatically infer whether a local variable is a constant, so the declaration of a local constant is not necessary.

Special top-level assignments default to constants, such as function and type keywords.

Note const has only an effect on the binding of variables, which can be bound to a variable object, such as an array, that can still be modified.