Callbacks#

Um callback é uma função que é passada como argumento para outra função.

A forma preferível de criar o callback é de prover uma abstract interface declarando a assinatura do callback. Isso permite que use checagem em tempo de compilação para o callback passado.

module integrals
  use types, only: dp
  implicit none
  private
  public :: simpson, integrable_function

  abstract interface
    function integrable_function(x) result(func)
      import :: dp
      real(dp), intent(in) :: x
      real(dp) :: func
    end function
  end interface

contains

  function simpson(f, a, b) result(s)
    real(dp), intent(in) :: a, b
    procedure(integrable_function) :: f
    real(dp) :: s

    s = (b-a) / 6 * (f(a) + 4*f((a+b)/2) + f(b))
  end function simpson

end module integrals

A função pode então ser usada com um callback ao importar o módulo como mostrado no exemplo a seguir

module demo_functions
  use types, only: dp
  implicit none
  private
  public :: test_integral

contains

  subroutine test_integral(a, k)
    real(dp), intent(in) :: a, k

    print *, simpson(f, 0._dp, pi)
    print *, simpson(f, 0._dp, 2*pi)
  contains

    function f(x) result(y)
      real(dp), intent(in) :: x
      real(dp) :: y
      y = a*sin(k*x)
    end function f
  end subroutine test_integral

end module demo_functions

Exportando a interface abstrata permite que você crie ponteiros de procedimento com a assinatura correto e também estender o callback além como mostrado aqui

module demo_integrals
  use types, only: dp
  use integrals, only: simpson, integrable_function
  implicit none
  private
  public :: simpson2, integrable_function

contains

  function simpson2(f, a, b) result(s)
    real(dp), intent(in) :: a, b
    procedure(integrable_function) :: f
    real(dp) :: s
    real(dp) :: mid
    mid = (a + b)/2
    s = simpson(f, a, mid) + simpson(f, mid, b)
  end function simpson2

end module demo_integrals