从另一个函数创建动态函数

7

我有一个Fortran 90子程序,它将函数作为参数,并且我想将该函数的修改版本传递到另一个子程序中。我希望程序看起来像这样:

subroutine foo(f, ...)
    real                 :: pt(2), dir(2)

    interface
    function f(x) result(y)
        real, intent(in) :: x(2)
        real             :: y
    end function f
    end interface

    pt = ...
    dir = ...
!! Somehow create g(x) = f(pt + x*dir)
    call bar(g)

end subroutine foo

subroutine bar(g)
    interface
    function g(x) result(y)
        real, intent(in) :: x
        real             :: y
    end function g
    end interface

!! Do stuff with g
end subroutine bar

当'g'只需要使用普通变量而不是函数时,我已经成功地做到了类似的事情。在这种情况下,我将其作为全局函数使用,使用全局变量,并在'foo'中分配给这些全局变量。然而,我找不到将'f'变成全局的方法,或将其分配给全局函数。

有人有任何想法如何做到这一点吗?解决方案可以尽可能地hacky。

2个回答

7
这并不容易。在某些语言中,您可以将指针传递给嵌套函数,称为“闭包”。在Fortran(或C和类似语言)中,这是不可能的,因为数据随着更高级别函数的堆栈被销毁。我建议您尝试使用函数对象,即一个带有函数指针(或更多)和所需函数数据的类。通过这种方式,您甚至可以进行函数组合和类似的功能性操作。

更多关于概念的信息请参见http://en.wikipedia.org/wiki/Function_object

下面是一个用于组合两个单参数函数的函数对象示例:

module ComposeObj
  use Parameters, only: rp
  use AritmFunctions, only: fce
  implicit none

  private
  public Compose

  type Compose
    private
    procedure(fce),pointer,nopass :: f1 => null(),f2=>null()
  contains
    procedure,public :: call => helper
  end type Compose

  interface Compose
    procedure NewCompose
  end interface

 contains

  function NewCompose(f,g)
    procedure(fce) :: f,g
    type(Compose) :: NewCompose

    NewCompose%f1 => f
    NewCompose%f2 => g
  end function NewCompose

  pure real(rp) function helper(this,x)
    class(Compose),intent(in) :: this
    real(rp),intent(in) :: x
    helper = this%f1(this%f2(x))
  end function helper

end module ComposeObj

谢谢提供范例,但是这个在Fortran 90中可行吗?你使用了很多我不熟悉的关键字;尤其是我只能在2003年的参考资料中找到“procedure”的相关信息,而在90年代并没有。 - Eric Langlois
不,过程指针是Fortran 2003的一个功能。 Fortran 90完全已经过时,如果非常保守,最早应该使用的标准是Fortran 95,其纠正了Fortran 90的几个问题。现代Fortran编程需要Fortran 2003和2008。 - Vladimir F Героям слава

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接