Closures in Fortran

Fortran supports anonymous functions, which can form closures. Anonymous functions are useful when you want to define a function inline without having to name it.

module closures
  implicit none
  private
  public :: int_seq

contains

  ! This function int_seq returns another function, which
  ! we define anonymously in the body of int_seq. The
  ! returned function closes over the variable i to
  ! form a closure.
  function int_seq() result(next_int)
    integer :: i
    procedure(integer_func), pointer :: next_int

    i = 0
    next_int => increment

  contains

    function increment() result(res)
      integer :: res
      i = i + 1
      res = i
    end function increment

  end function int_seq

end module closures

program main
  use closures
  implicit none

  procedure(integer_func), pointer :: next_int
  procedure(integer_func), pointer :: new_ints

  ! We call int_seq, assigning the result (a function)
  ! to next_int. This function value captures its
  ! own i value, which will be updated each time
  ! we call next_int.
  next_int => int_seq()

  ! See the effect of the closure by calling next_int
  ! a few times.
  print *, next_int()
  print *, next_int()
  print *, next_int()

  ! To confirm that the state is unique to that
  ! particular function, create and test a new one.
  new_ints => int_seq()
  print *, new_ints()

end program main

! Interface for the function type
abstract interface
  function integer_func() result(res)
    integer :: res
  end function integer_func
end interface

To compile and run this Fortran program:

$ gfortran -o closures closures.f90
$ ./closures
           1
           2
           3
           1

In Fortran, we use a module to encapsulate the closure-like behavior. The int_seq function returns a pointer to a function, which is our way of implementing a closure. The internal function increment acts as the anonymous function in the original example.

The contains keyword in Fortran allows us to define internal procedures, which can access variables from their containing scope, similar to closures in other languages.

The abstract interface at the end defines the function type we use for our function pointers.

While Fortran doesn’t have true anonymous functions or closures in the same way as some other languages, this approach provides similar functionality.

The last feature of functions we’ll look at for now is recursion, which Fortran fully supports.