I'm a bit confused about the use of an interface block inside a module and the use of the CONTAINS statement to create an "explicit interface" for a procedure inside a module.
I usually write a procedure using an interface block inside a module. For example,
MODULE ModExample
INTERFACE
SUBROUTINE Sumatory(a, b, c)
IMPLICIT NONE
INTEGER, INTENT(IN)::a
INTEGER, INTENT(OUT)::b
INTEGER, INTENT(OUT)::c
END SUBROUTINE Sumatory
END INTERFACE
END MODULE ModExample
SUBROUTINE Sumatory(a, b, c)
IMPLICIT NONE
INTEGER, INTENT(IN)::a
INTEGER, INTENT(OUT)::b
INTEGER, INTENT(OUT)::c
!Executable statements here
END SUBROUTINE Sumatory
And this works for me. But it can also be written using the CONTAINS stament inside the module, and actually this is the way in which example procedures are written in the Fortran books that I've consulted.
MODULE ModExample
CONTAINS
SUBROUTINE Sumatory(a, b, c)
IMPLICIT NONE
INTEGER, INTENT(IN)::a
INTEGER, INTENT(OUT)::b
INTEGER, INTENT(OUT)::c
!Executable statements here
END SUBROUTINE Sumatory
END MODOULE ModExample
So what is wrong with the INTERFCE block? Are both equivalent constructs? Which of the two aproaches should I use? Maybe all this questions can be answered with a big "it depends" but I would like you to give an explanation about their differences. Thanks in advance.
An INTERFACE block specifies the forms of reference by which a procedure can be invoked. An interface block specifies a procedure interface, a defined operation, or a defined assignment. An INTERFACE statement begins an interface block. An END INTERFACE statement ends an interface block.
A procedure is a group of statements that perform a well-defined task and can be invoked from your program. Information (or data) is passed to the calling program, to the procedure as arguments.
A module is like a package where you can keep your functions and subroutines, in case you are writing a very big program, or your functions or subroutines can be used in more than one program. Modules provide you a way of splitting your programs between multiple files.
A procedure is a unit of code enclosed either between the Suband End Sub statements or between the Function and End Function statements. A procedure should accomplish a simple well-defined task. Modules are workbook sheets that contain code. Each module can contain a declarations section followed by procedures.
It depends, but unless you have a good reason to the contrary, use module procedures ("after the contains").
The thing that is "wrong" with the first approach is that you have had to specify the interface of the procedure twice - once in the interface block and once in the procedure definition itself. In the second case the interface is only specified once - in the procedure definition. The need to maintain multiple specifications is a potential source of error.
Elaborating:
In the first code example, the source between the latter SUBROUTINE and END SUBROUTINE statements (not inside the interface block) is what's known as an external subprogram. This is a program unit in its own right. The external subprogram defines an external procedure.
In the second code example, the source between the SUBROUTINE and END SUBROUTINE statements, that appears after the CONTAINS statement in the module, is a module subprogram. It is part of the module program unit. That module subprogram defines a module procedure.
(A "subprogram" refers to the source code construct, while a procedure refers to the thing that the source code defines.)
There also exist internal subprograms (they appear after the CONTAINS statement inside a host external or module subprogram, or main program) which define internal procedures, and separate module subprograms, which are another way of defining module procedures.
Fortran program units (main programs, modules, submodules, external subprograms, block data) use a model of separate compilation. When compiling a particular program unit, the compiler acts as if it is oblivious to any other program unit in the program, bar explicit specifications in the source to the contrary.
One consequence of this is that if you reference an external procedure in a scope without explicitly telling the compiler what that external procedure looks like, then the compiler must implicitly deduce the interface for the external procedure from the manner of the reference (the procedure has an implicit interface). Procedures referenced in such a manner cannot use many of the newer argument passing features of the language (because the compiler doesn't know how to invoke and pass arguments to the procedure correctly). Practically compilers are also much less likely to identify errors such as mismatched argument types.
An interface block, such as the one in the first code example, can be used to explicitly specify the interface of an external procedure. References to the external procedure in source code where that explicit interface is accessible can use all the modern argument passing features and are likely to get much better compiler error detection. However, it is still incumbent on the programmer to make sure that the relevant characteristics of the interface body and actual external procedure definition are consistent.
The language also has a requirement that only one interface for a procedure be accessible in a scoping unit. Inside the external subprogram that defines it the interface for the procedure is already explicit, so it is incumbent on the programmer to make sure that an interface body for the same external procedure is not accessible inside the external procedure.
One of the explicit specifications that allows information to be shared between program units is a USE statement, which makes knowledge about the things defined by a module available in the scope where the USE statement appears. This includes knowledge about the procedures defined or declared by the module.
(The language requires that the source for the public portions of a module "be available" before the module is used, which practically means that the source for the module must have been compiled before a USE statement for the module is compiled.)
Unlike external procedures, the interface for a module procedure or internal procedure is always explicit in a scope where its identifier is accessible - there is no need to have a interface body for the module procedure or internal (separate module subprograms aside, you must not have an interface body).
In summary:
First example - you have a module with an interface body for an external procedure, and then the external procedure itself. You can reference that external procedure without needing to USE the module, in which case an implicit interface is used (limited features, error prone). Alternatively if the module is USE'd in the referencing scope the interface will be explicit. In that case the programmer must ensure that the interface body and external procedure definition match and that the interface body for the external procedure is not accessible inside the external procedure. This is error prone and a maintenance nuisance.
Second example - you have a module that has a module procedure. You cannot reference the module procedure through its name without USE'ing the relevant module. The interface for such a reference will always be explicit. There is no need to maintain a separate interface body for the procedure.
The only good reason to us the first form over the second form is if you need to break a compilation dependency loop or otherwise limit a long compilation dependency chain.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With