Функции обратного вызова#

Функция обратного вызова – это функция, которая передаётся в качестве аргумента в другую функцию.

Предпочтительным способом создания такой функции обратного вызова является предоставление абстрактного интерфейса, объявляющего сигнатуру функции обратного вызова. Это позволяет использовать проверку времени компиляции для переданной функции обратного вызова.

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

После этого функцию можно использовать в качестве функции обратного вызова, импортировав модуль, как показано в следующем примере

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

Экспорт абстрактного интерфейса позволяет создавать указатели подпрограмм с правильной сигнатурой, а также расширять функции обратного вызова, как показано здесь

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