SELF-TEST EXERCISES 4.1
4.9 Modules and explicit procedure interfaces
We have several times referred to the interface of a procedure in a relatively informal manner, and have indicated that it consists of the name of the procedure (and its type if it is a function), together with the number and type of its arguments. We must now, briefly, examine this concept in slightly more detail.
Traditionally, in FORTRAN 77 and earlier versions of FORTRAN, a call to a subroutine or reference to a function was made without the calling program unit knowing anything about the procedure being called at all! After all the program units that constituted the complete program had been compiled a special program would link them together and would ensure that if, somewhere in the set of program units being linked together, there was a call or reference to the procedure MINE then a procedure calledMINE was indeed available; if it was not, then an error would be generated. When the call or reference to the procedure MINE was obeyed, the actual arguments would be made available, in the correct order, and the procedure MINE would use them, in the same order, as its dummy arguments.
This process meant that the calling program unit knew nothing about the procedure, and vice versa. In this situation the called procedure is said to have an implicit interface. Although this form of interface does not provide the information necessary for checking that the actual arguments match the dummy arguments, it was a convenient approach, and had the great advantage that procedures could be written without any knowledge about other procedures being utilized in the same program, apart from the programmer's knowledge of the interface specification of any called procedures.
However, as we saw in Section 4.5, if the additional features provided in Fortran 90 for security and other purposes are to operate properly, they need more information about any procedures being used than is available from an implicit interface. Furthermore, as we shall see in later chapters, some of the most powerful features of Fortran 90 can only work if they have a full knowledge of any relevant procedure interfaces. This requires that the procedures concerned have an explicit interface.
We shall investigate exactly what is meant by an explicit interface in Chapter 11, and will see how we can specify this to a calling program unit.
However, there is one way that we can always make the interface of a procedure explicit, namely by placing the procedure in a module. The rules relating to modules specify that
• the interfaces of all the procedures defined within a single module are explicit to each other
• the interfaces of any procedures made available by USE association are explicit in the program unit that is using the module
Although, as we shall see in Chapter 12, we can include procedure definitions in the same modules as both type and variable declarations, there are
116 Basic building blocks
certain complications that it is not appropriate to discuss at this stage. For the present, therefore, we recommend that procedures are contained in one module, or possibly more than one, while other entities are contained in a different module, or modules.
There is one additional statement required in a module that contains a procedure, which is occasioned by the fad that a procedure in a m~dule is a program unit nested within another program unit. This statement consists of the single word
CONTAINS
which must be placed. before the first procedure within a module. Thus, if the subroutine problem_sub (see Figure 4.12) which was used earlier to illustrate the use of the INTENT attribute were to be placed in a module, the module might be as follows:
MODULE my_procedures IMPLICIT NONE CONTAINS
SUBROUTINE problem_sub(argl,arg2,arg3) IMPLICIT NONE
This subroutine returns the product of its first two arguments via the third argument
INTEGER:: argl,arg2,arg3 argl = arg2*arg3
END SUBROUTINE problem_sub END MODULE my-procedures
The program that called the subroutine would then USE this module:
PROGRAM intent_demonstration USE my-procedures
IMPLICIT NONE
INTEGER, PARAMETER a=2 INTEGER :: b=3,c=4,d CALL problem_sub(a,b,c) CALL problem_sub(b,c,d) END PROGRAM intent_demonstration
Modules and explicit procedure interfaces 117 Because the subroutine problem_sub is made available through USE
association its interface is explicit in the calling program, and so checking that the actual arguments and the corresponding dummy arguments agree in type as well as in intent is carried out, thus providing much greater security at compile time. In addition, if the module my-procedures contains several procedures, then each of these has an explicit interface to all the other procedures within that module.
Thus a group of related procedures can all be encapsulated within a single module, with consequent benefits in manipulation of the group and of their links with each other.
If the procedures contained in one module reference procedures contained in another module then, as we have already seen, the first module may USE the second. However, care must be taken that the second module does not also, either diredly or indiredly, USE the first one, for that is forbidden, as was stated in Sedion 4.7.
We shall investigate the use of modules in more detail in Chapter 12 and recommend that until then you keep your use of modules as simple as possible.
However, we strongly recommend that all procedures are encapsulated in a module henceforth, both to enable the processor to carry out a higher level of argument checking than might otherwise be the case and, possibly even more important, so that some of the valuable features of Fortran that we shall meet in the next few chapters, but which require an explicit interface, can be used without any difficulty.
ill
ProblemIn Example 3.3 we created two geometric derived types, point and line, and wrote a program to determine the line joining two points. Rewrite this example so that the types are stored in a module, and the line is determined by a procedure which is stored in another module. (We shall add further types and procedures to these two modules in later chapters.)
11]
AnalysisWe have already carried out the analysis for this problem, and it merely remains to create two strudure plans for the procedure and a main program with which to test it:
1 Read coordinates of two points
2 Call subroutine (line_twoJoints) to calculate 3 Print the equation of the line
118 Basic building blocks
rn
SolutionMODULE geometric_data IMPLICIT NONE SAVE
! Type definitions TYPE point
REAL:: x,y END TYPE point TYPE line
REAL:: a,b,c END TYPE line
l'
Cartesian coordinates of the point
coefficients of defining equation
END MODULE geometric_data MODULE geometric_procedures
USE geometric_data IMPLICIT NONE CONTAINS
SUBROUTINE line_two_points(line_l,point_l,point_2) IMPLICIT NONE
! Dummy arguments TYPE (line) , INTENT (OUT) TYPE (point) , INTENT~IN) ,
line_l
point_l,point_2
! Calculate coefficients of equation representing the line line_l%a = point_2%y - point_l%y
line_l%b = point_l%x - point_2%x
line_l%c = point_l%y*point_2%x - point_2%y*point_l%x END SUBROUTINE line_two_points
END MODULE geometric_procedures PROGRAM geometry
USE geometric_procedures IMPLICIT NONE
! A program to test the subroutine line_two-points
Modules as an aid to program design 119
! Variable declarations TYPE (point) :: pl,p2 TYPE (line) :: pl_to-p2
! Read data
PRINT *,"Please type coordinates of first point"
READ * ,pl
PRINT *,"Please type coordinates of second point"
READ * ,p2
! Call procedure to calculate the equation of the line CALL line_two_points (pl_to-p2 ,pl ,p2)
! Print result
PRINT *,"The equation of the line joining these two points is"
PRINT *,"ax
+
by+
c = 0"PRINT *, "where a = ",pl_to-p2%a PRINT *," b = ",pl_to-p2%b PRINT *," c = ",pl_to-p2%c END PROGRAM Geometry
Note that it is not necessary for the subroutine line_two-points to USE the module geometric_data since the module geometric-procedures, in which it is placed, already does so. In a similar fashion, it is not necessary for the program geometry to USE both modules, since accessing geometric_procedures also makes the entities declared in geometric_data available by USE association.