コールバック#
コールバックは、別の関数に引数として渡される関数です。
そのようなコールバックを作成する推奨方法は、コールバックのシグネチャを宣言する抽象インタフェースを提供することです。これにより、渡されたコールバックのコンパイル時のチェックを使用できます。
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