Procedures: Functions & Subroutines

Functions return a value and should be free of side effects; subroutines are called with call and return results through arguments.

13.1 Functions

module geometry
  implicit none
  integer, parameter :: dp = kind(1.0d0)
contains
  function circle_area(r) result(area)
    real(dp), intent(in) :: r
    real(dp) :: area
    area = acos(-1.0_dp) * r**2
  end function circle_area

  real(dp) function hypotenuse(a, b)        ! alternative style: type before 'function'
    real(dp), intent(in) :: a, b
    hypotenuse = sqrt(a**2 + b**2)
  end function hypotenuse
end module geometry

program main
  use geometry
  implicit none
  print *, circle_area(2.0_dp), hypotenuse(3.0_dp, 4.0_dp)
end program main

13.2 Subroutines

Functions return a value and should be free of side effects; subroutines are called with call and return results through arguments.

subroutine swap(a, b)
  real, intent(inout) :: a, b
  real :: tmp
  tmp = a; a = b; b = tmp
end subroutine swap

subroutine stats(x, mean, stdev)
  real, intent(in) :: x(:)
  real, intent(out) :: mean, stdev
  mean = sum(x) / size(x)
  stdev = sqrt(sum((x - mean)**2) / (size(x) - 1))
end subroutine stats

call swap(p, q)
call stats(data, m, s)

13.3 INTENT

read-only inside the procedure undefined on entry; must be set (allocatables are deallocated on entry) read and modified pass a copy (by value)

Always declare intent — it documents the interface and lets the compiler catch bugs.

13.4 Argument passing

Fortran passes arguments by reference (conceptually), so a procedure can modify actual arguments. Passing an expression or constant to an intent(out)/intent(inout) argument is an error.

13.5 Where procedures live

Module procedures (inside contains of a module) — get automatic explicit interfaces: argument checking, assumed-shape arrays, optional arguments. Preferred.

Internal procedures (inside contains of a program or procedure) — can access the host's variables.

External procedures (separate, legacy) — need an interface block for safety.

13.6 Interface blocks

Needed for external procedures and procedure arguments (or use procedure(...) with an abstract interface).

interface
  function f(x) result(y)
    real, intent(in) :: x
    real :: y
  end function f
end interface