Closures in Co-array Fortran

Co-array 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_mod
  implicit none
  private
  public :: int_seq

contains

  function int_seq() result(next_int)
    integer :: i[*]
    procedure(int_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_mod

program main
  use closures_mod
  implicit none

  procedure(int_func), pointer :: next_int
  procedure(int_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 integer function
abstract interface
  function int_func() result(res)
    integer :: res
  end function int_func
end interface

In this Co-array Fortran version, we’ve implemented a similar concept of closures using a module and function pointers. The int_seq function returns a pointer to an internal function increment, which acts as our closure.

To run the program, save it as closures.f90 and compile it with a Co-array Fortran-compatible compiler:

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

The output demonstrates that the closure maintains its state between calls, and a new closure starts with a fresh state.

Note that Co-array Fortran doesn’t have built-in support for anonymous functions or closures in the same way as some other languages. This implementation uses function pointers and internal procedures to achieve similar functionality.

The last feature of functions we’ll look at for now is recursion, which is fully supported in Co-array Fortran.