Wywołania zwrotne (callbacks)#
Wywołanie zwrotne to funkcja przekazywana innej funkcji jako argument.
Preferowanym sposobem tworzenia wywołań zwrotnych jest zapewnienie abstrakcyjnego interfejsu deklarującego sygnaturę wywołania zwrotnego. Pozwala to na użycie kontroli czasu kompilacji dla przekazanego wywołania zwrotnego.
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
Funkcja może być następnie użyta z wywołaniem zwrotnym przez zaimportowanie modułu, tak jak pokazano w następującym przykładzie
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
Eksportowanie abstrakcyjnego interfejsu pozwala na tworzenie wskaźników procedur z poprawną sygnaturą oraz na dalsze wydłużenie wywołania zwrotnego, tak jak pokazano poniżej
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