In the previous section, we learned that Fortran’s strong typing discipline prohibits passing arguments of incompatible data types to procedures. This means that when you write a function that expects a real number as input, you can’t simply pass an integer as an input argument. This would trigger a compile-time error. You can see this for yourself right now. Start with a basic function to compute the average of a one-dimensional real array:
pure real function average(x) result(res)
real, intent(in) :: x(:) ❶
res = sum(x) / size(x) ❷
end function average
❷ Sum of all elements divided by the number of elements
Attempting to invoke average with an array of integers–say, average([1, 6, 4])–the compiler will report an error:
gfortran mod_average_incompatible.f90
mod_average_incompatible.f90:20:10: ❶
print *, average([1, 6, 4]) ❷
1
Error: Type mismatch in argument ‘x’ at (1); ❸
passed INTEGER(4) to REAL(4) ❸
❶ File name, row, and column where the error occurred
❷ The source code that triggered the error
In this case, the error message is quite helpful. The compiler tells us that there’s a type mismatch for argument x, as well as which data type was passed (INTEGER(4)) and which was expected (REAL(4)). Here, the number 4 corresponds to the default type kind of 4 bytes–int32 and real32 literal constants from the iso_fortran_env module. We could do due diligence and make sure that we pass an argument with a matching type to every procedure. However, being able to pass data to a function without having to worry about the type is convenient and will help you write shorter and more correct code.
To implement a generic function to compute an average of arrays of different data types, we’ll go through the following steps:
- Write the specific functions for each data type; these functions must have unique names.
- Write the interface (generic procedure) that points to the specific functions.
- Make the interface publicly available in the module.
- Apply the generic procedures to the data.