Функции обратного вызова#
Функция обратного вызова – это функция, которая передаётся в качестве аргумента в другую функцию.
Предпочтительным способом создания такой функции обратного вызова является предоставление абстрактного интерфейса, объявляющего сигнатуру функции обратного вызова. Это позволяет использовать проверку времени компиляции для переданной функции обратного вызова.
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