James Wright
James Wright

Reputation: 1435

Difference between subroutine inside module "contains" and outside module

I have a large source code where subroutines in modules are defined outside the module ... end module statement (ie. not inside a contains statement). I've included a simplified module below:

module core
  implicit none

  type :: disc_status
    sequence

    real*8 :: alpha1, alpha2, alpha3

  end type disc_status
end module core

subroutine tester(input)
  use core
  type(disc_status), intent(in) :: input
  print *, input%alpha1, input%alpha2, input%alpha3
end subroutine tester

Here's an example program using the module and subroutine:

program flyingDiscSimulator

use core
implicit none

type(disc_status) :: disc

disc%alpha1 = 1.1D0
disc%alpha2 = 1.2D0
disc%alpha3 = 1.3D0

call tester(disc)

print *, 'it works'

end program flyingDiscSimulator

Normally, I end up seeing subroutines use the contains statement within a module:

module core
  implicit none

  type :: disc_status
    sequence

    real*8 :: alpha1, alpha2, alpha3

  end type disc_status

   contains
     subroutine tester(input)
       type(disc_status), intent(in) :: input
       print *, input%alpha1, input%alpha2, input%alpha3
     end subroutine tester

end module core

However, the program file referenced above doesn't require any changes to use either way of including a subroutine in a module (using gfortran anyways). Thus, there appears to be no difference in the usage of the module or it's subroutine between the two solutions. Are there any "under the hood" differences between the two styles?

Upvotes: 3

Views: 509

Answers (2)

francescalus
francescalus

Reputation: 32431

The versions

module m
contains
  subroutine s()
  end subroutine s
end module m

and

module m
end module m

subroutine s()
end subroutine s

say completely different things, but in the case of the question the end results are much the same.

The first version here creates a module procedure s with host m; the second version has an external procedure s with no host.

Although the example of the question has the external procedure using the module, there is more generally a difference: the module procedure has access to all entities in the module (except when made inaccessible through an import statement or by being obscured by local names; the external procedure using the module has access only to those public entities.

However, come the main program the effects are different. The external subroutine and its name are global entities. Going to my second version, then

program main
  call s
end program

is a valid program which calls the external subroutine s. This subroutine reference is valid because the implicit interface for s in the main program suffices. If the external subroutine s were such than an explicit interface were required then main program here would not be allowed. It is acceptable, but not required, to have an external s statement in the main program to reinforce to the reader that the subroutine is an external one (with implicit interface). (implicit none external would make external s necessary.)

The example of the question is such that an explicit interface is not required.

A module procedure always has an explicit interface available when accessible. However, a module procedure is not a global entity and its name is not a global identifier.

Under the hood, there are implementation differences (stemming from the above): most notably compilers will often "name mangle" module procedures.

In summary, there are differences between the two approaches of the question, but they won't be noticed by the programmer in this case.

Upvotes: 4

jack
jack

Reputation: 1790

The procedure inside the module will have an explicit interface (aka the compiler knows about the arguments' characteristics). Whereas the procedure outside of the module will have an implicit interface (aka the compiler must make assumptions about the arguments).

Explicit interfaces help the compiler to find programming errors and are therefore favourable. For a more indepth discussion of advantages see for example this answer.


I am not even sure if it is valid Fortran to call tester inside the program when it is defined outside of core?

The line use core should just make the module's public objects known and the tester procedure needs its own external tester line.

Upvotes: 0

Related Questions