Functions and subroutines, in conjunction with modules, are the tools to break down a program into units. This makes the program more readable and manageable. Each one of these units can be thought of as part of the code that, ideally, could be compiled and tested in isolation. The main program(s) can call (or invoke) such subprograms (functions or subroutines) to accomplish a task.
Functions and subroutines are different in the following sense:
Functions and subroutines collectively go under the name of procedures. (In the following we will use the verb "call" as synonym of "invoke" even if technically the procedures to be
functions appear as right hand side of assignment or in expressions.)
Functions can be written using several types of syntax
function name() integer name name = 42 end function
integer function name() name = 42 end function
function name() result(res) integer res res = 42 end function
Functions return values through a function result. Unless the function statement has a
result clause the function's result has the same name as the function. With
result the function result is that given by the
result. In each of the first two examples above the function result is given by
name; in the third by
The function result must be defined during execution of the function.
Functions allow to use some special prefixes.
Pure function means that this function has no side effect:
pure real function square(x) real, intent(in) :: x square = x * x end function
Elemental function is defined as scalar operator but it can be invoked with array as actual argument in which case the function will be applied element-wise. Unless the
impure prefix (introduced in Fortran 2008) is specified an elemental function is also a pure function.
elemental real function square(x) real, intent(in) :: x square = x * x end function
return statement can be used to exit function and subroutine. Unlike many other programming languages it is not used to set the return value.
real function f(x) real, intent(in) :: x integer :: i f = x do i = 1, 10 f = sqrt(f) - 1.0 if (f < 0) then f = -1000. return end if end do end function
This function performs an iterative computation. If the value of
f becomes negative the function returns value -1000.
In Fortran functions and subroutines need to be explicitly declared as recursive, if they are to call themselves again, directly or indirectly. Thus, a recursive implementation of the Fibonacci series could look like this:
recursive function fibonacci(term) result(fibo) integer, intent(in) :: term integer :: fibo if (term <= 1) then fibo = 1 else fibo = fibonacci(term-1) + fibonacci(term-2) end if end function fibonacci
Another example is allowed to calculate factorial:
recursive function factorial(n) result(f) integer :: f integer, intent(in) :: n if(n == 0) then f = 1 else f = n * f(n-1) end if end function factorial
For a function to directly recursively reference itself its definition must use the
It is not possible for a function to be both
intent attribute of a dummy argument in a subroutine or function declares its intended use. The syntax is either one of
intent(IN) intent(OUT) intent(INOUT)
For example, consider this function:
real function f(x) real, intent(IN) :: x f = x*x end function
intent(IN) specifies that the (non-pointer) dummy argument
x may never be defined or become undefined throughout the function or its initialization. If a pointer dummy argument has the attribute
intent(IN), this applies to its association.
intent(OUT) for a non-pointer dummy argument means that dummy argument becomes undefined on invocation of the subprogram (except for any components of a derived type with default initialization) and is to be set during execution. The actual argument passed as dummy argument must be definable: passing a named or literal constant, or an expression, is not allowed.
Similarly to before, if a pointer dummy argument is
intent(OUT) the association status of the pointer becomes undefined. The actual argument here must be a pointer variable.
intent(INOUT) specifies that the actual argument is definable and is suitable for both passing in and returning data from the procedure.
Finally, a dummy argument may be without the
intent attribute. Such a dummy argument has its use limited by the actual argument passed.
For example, consider
integer :: i = 0 call sub(i, .TRUE.) call sub(1, .FALSE.) end subroutine sub(i, update) integer i logical, intent(in) :: update if (update) i = i+1 end subroutine
i can have no
intent attribute which allows both of the subroutine calls of the main program.
For a function or subroutine to be useful it has to be referenced. A subroutine is referenced in a
and a function within an expression. Unlike in many other languages, an expression does not form a complete statement, so a function reference is often seen in an assignment statement or used in some other way:
x = func(...) y = 1 + 2*func(...)
There are three ways to designate a procedure being referenced:
The first can be seen as
procedure(), pointer :: sub_ptr=>sub call sub() ! With no argument list the parentheses are optional call sub_ptr() end subroutine sub() end subroutine
and the final two as
module mod type t procedure(sub), pointer, nopass :: sub_ptr=>sub contains procedure, nopass :: sub end type contains subroutine sub() end subroutine end module use mod type(t) x call x%sub_ptr() ! Procedure component call x%sub() ! Binding name end
For a procedure with dummy arguments the reference requires corresponding actual arguments, although optional dummy arguments may be not given.
Consider the subroutine
subroutine sub(a, b, c) integer a, b integer, optional :: c end subroutine
This may be referenced in the following two ways
call sub(1, 2, 3) ! Passing to the optional dummy c call sub(1, 2) ! Not passing to the optional dummy c
This is so-called positional referencing: the actual arguments are associated based on the position in the argument lists. Here, the dummy
a is associated with
c (when specified) with
Alternatively, keyword referencing may be used when the procedure has an explicit interface available
call sub(a=1, b=2, c=3) call sub(a=1, b=2)
which is the same as the above.
However, with keywords the actual arguments may be offered in any order
call sub(b=2, c=3, a=1) call sub(b=2, a=1)
Positional and keyword referencing may both be used
call sub(1, c=3, b=2)
as long as a keyword is given for every argument following the first appearance of a keyword
call sub(b=2, 1, 3) ! Not valid: all keywords must be specified
The value of keyword referencing is particularly pronounced when there are multiple optional dummy arguments, as seen below if in the subroutine definition above
b were also optional
call sub(1, c=3) ! Optional b is not passed
The argument lists for type-bound procedures or component procedure pointers with a passed argument are considered separately.