Since a main program could contain many functions and in fact a function can contain other functions (i.e., nested functions), one may ask the following questions:
The simplest rule is the following:
| Scope Rule 1 |
The scope of an entity is the program or function in which it is declared. |
Therefore, in the following, the scope of parameter PI and variables m and n is the main program, the scope of formal argument k and REAL variables f and g is function Funct1(), and the scope of formal arguments u and v is function Funct2().
PROGRAM Scope_1
IMPLICIT NONE
REAL, PARAMETER :: PI = 3.1415926
INTEGER :: m, n
...................
CONTAINS
INTEGER FUNCTION Funct1(k)
IMPLICIT NONE
INTEGER, INTENT(IN) :: k
REAL :: f, g
..........
END FUNCTION Funct1
REAL FUNCTION Funct2(u, v)
IMPLICIT NONE
REAL, INTENT(IN) :: u, v
..........
END FUNCTION Funct2
END PROGRAM Scope_1
There is a direct consequence of Scope Rule 1. Since an entity
declared in a function has a scope of that function, this entity cannot be
seen from outside of the function. In the above example, formal argument
k and variables f and g are declared within function
Funct1(), they are only "visible" in function Funct1() and
are not visible outside of Funct1(). In other words, since k,
f and g are not "visible" from the main program and function
Funct2(), they cannot be used in the main program and function
Funct2(). Similarly, the main program and function Funct1()
cannot use the formal arguments u and v and any entity
declared in function Funct2().
This comes the second scope rule:
| Scope Rule 2 |
A global entity is visible to all contained functions, including the function in which that entity is declared. |
Continue with the above example, since m and n are global to both functions Funct1() and Funct2(), they can be used in these two functions.
PROGRAM Scope_2
IMPLICIT NONE
INTEGER :: a = 1, b = 2, c = 3
WRITE(*,*) Add(a)
c = 4
WRITE(*,*) Add(a)
WRITE(*,*) Mul(b,c)
CONTAINS
INTEGER FUNCTION Add(q)
IMPLICIT NONE
INTEGER, INTENT(IN) :: q
Add = q + c
END FUNCTION Add
INTEGER FUNCTION Mul(x, y)
IMPLICIT NONE
INTEGER, INTENT(IN) :: x, y
Mul = x * y
END FUNCTION Mul
END PROGRAM Scope_2
In the above program, variables a, b and c are global to
both functions Add() and Mul(). Therefore, since variable
c used in function Add() is global to Add(), expression
q + c means computing the sum of the value of the formal argument
q and the value of global variable c. Therefore, the first
WRITE produces 4 (= 1 + 3). Before the second WRITE, the
value of c is changed to 4 in the main program. Hence, the
second WRITE produces 5 (= 1 + 4). The third WRITE produces
8 (= 2 * 4).
Thus, the first two WRITEs produce different results even though their actual arguments are the same! This is usually refereed to as a side effect. Therefore, if it is possible, avoid using global variables in internal functions.
Let us continue with the above example. To remove side effect, one could add one more argument to function Add() for passing the value of c.
PROGRAM Scope_2
IMPLICIT NONE
INTEGER :: a = 1, b = 2, c = 3
WRITE(*,*) Add(a, c)
c = 4
WRITE(*,*) Add(a, c)
WRITE(*,*) Mul(b,c)
CONTAINS
INTEGER FUNCTION Add(q, h)
IMPLICIT NONE
INTEGER, INTENT(IN) :: q, h
Add = q + h
END FUNCTION Add
INTEGER FUNCTION Mul(x, y)
IMPLICIT NONE
INTEGER, INTENT(IN) :: x, y
Mul = x * y
END FUNCTION Mul
END PROGRAM Scope_2
| Scope Rule 3 |
An entity declared in the scope of another entity is
always a different entity even if their names are identical. |
In the program below, the main program declares a variable i, which is global to function Sum(). However, i is also declared in function Sum(). According to Scope Rule 3 above, these two is are two different entities. More precisely, when the value of Sum()'s i is changed, this change will not affect the i in the main program and vice versa. This would save us a lot of time in finding variables with different names.
PROGRAM Scope_3
IMPLICIT NONE
INTEGER :: i, Max = 5
DO i = 1, Max
Write(*,*) Sum(i)
END DO
CONTAINS
INTEGER FUNCTION Sum(n)
IMPLICIT NONE
INTEGER, INTENT(IN) :: n
INTEGER :: i, s
s = 0
DO i = 1, n
s = s + i
END DO
Sum = s
END FUNCTION Sum
END PROGRAM Scope_3