使用函数作为参数——如何调用?

Using functions as arguments - how to call?

我有以下代码,我从一个子例程调用一个函数,它们都在同一个模块中:

      module mymodule
      implicit none
      contains  

      subroutine mycode
      real :: y0(3), a = 0.0, b = 1.0
      integer :: i, N = 10
      real, allocatable :: y(:,:)
      y0(:) = [1.0, 1.0, 1.0]
      y = AB2(od, a, b, N, y0)
      do i = 1, N
          print *, y(:,i)
      end do      
      end subroutine mycode

      function AB2(f, a, b, N, y0)
          real, allocatable :: AB2(:,:)
          interface
              function f(x, y)
                  real, allocatable :: f(:)
                  real, intent(in) :: x, y(:)
              end function
          end interface
          real, intent(in) :: a, b
          integer, intent(in) :: N
          real, intent(in) :: y0(:)
          real :: xn0, xn1, step
          real, allocatable :: yn0(:), yn1(:)
          integer :: i
          allocate(AB2(size(y0),N))
          step = (b-a)/(N-1)
          AB2(:,1) = y0
          AB2(:,2) = y0 + step*f(a, y0)
          do i = 3, N
              xn0 = a+(i-2)*step
              xn1 = a+(i-1)*step
              yn0 = AB2(:,i-2)
              yn1 = AB2(:,i-1)
              AB2(:,i) = AB2(:,i-1) + step*(3.0/2.0*f(xn1,yn1)
     &             -0.5*f(xn0,yn0))
          end do
      end function

      function od(x, y)
          real, allocatable :: od(:)
          real, intent(in) :: x, y(:)
          allocate(od(3))
          od(1) =  x + y(1)
          od(2) = -y(3) - y(2) - x
          od(3) =  x - y(1) + y(3)
      end function

      end module mymodule

如果我想给函数 od 另一个参数,比如说 c,我必须把它包含在这一行

real, intent(in) :: x, c, y(:)

还有

   function od(x,c,y)

但是,我应该在哪里提供这个参数的值呢?调用中没有选项

y = AB2(od, a, b, N, y0)

此答案不会尝试重复 Fortran minimization of a function with additional arguments Passing external function of multiple variables as a function of one variable in Fortran or 的答案,而是在非常基本的层面上介绍问题。

假设您有一个函数 AB2 和另一个小函数 od

它们的使用方式是 AB2 接受 od 作为参数,因此您调用

y = AB2(od)

函数看起来像

real function AB2(f)
  interface
    real function f(x)
      real x
    end function
  end interface
  ... call f(x) here ...
end function

real function od(x)
  real x
end function

您需要将额外的数据 c 传递给 od。怎么做?

您不能仅通过为 c 添加参数来更改 od 而保持 AB2 不变。 AB2 包含参数 fod(x,c)f(x) 不兼容的接口的描述。

此外,您将无法将数据传递给 AB2。你肯定做不到

y = AB2(od(c))

通过执行 od(c) 您正在通过调用 od(x) 计算一个数字,然后您将尝试将此数字传递给 AB2 而不是应该传递的函数。

有几种方法可以缓解这种情况。它们在上面链接的答案中进行了描述。我将展示一种简单的可能性。

假设我们有函数 od(b,x),我们需要将 c 传递给 b,但我们不知道如何使用我们的 AB2 .

 real function od(b,x)
   real b, x
 end function

在我们的调用代码中,我们创建了一个包装函数,它为我们调用 odc。它可以是内部函数或模块函数。然后我们将 wrapper 传递给 AB2.

subroutine caller(c)
  y = AB2(wrapper)
contains
  real function wrapper(x)
    real x
    !we must be able to see c from here, by host association or by using a module
    wrapper = od(c,x)
  end function
end subroutine