2012-03-13 64 views
3

我有一个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'全局化,或将其分配给全局函数。

任何人有任何想法如何做到这一点?解决方案可以像你想要的那样简单。

回答

4

这并不容易。在某些语言中,您可以在所谓的closure中传递指向嵌套函数的指针。这在Fortran(或C语言和类似语言)中是不可能的,因为数据被堆栈中的高级函数破坏。我建议您尝试功能对象,即带有function pointer(或更多)的class以及该功能所需的数据。这样你甚至可以做功能组合和类似功能的东西。

更多概念http://en.wikipedia.org/wiki/Function_object

下面是用于两个单参数的函数组合物中的功能对象的样品:

module ComposeObj 
    use Parameters 
    use AritmFunctions 
    implicit none 

    private 
    public Compose 

    type Compose 
    private 
    procedure(fce),pointer,nopass :: f1 => null(),f2=>null() 
    contains 
    procedure,public :: call => helper 
    endtype 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(KND) function helper(this,x) 
    class(Compose),intent(in) :: this 
    real(KND),intent(in) :: x 
    helper = this%f1(this%f2(x)) 
    end function helper 

end module ComposeObj 
+0

感谢您的例子,但将它在Fortran 90的工作?你使用的很多关键词对我来说都是新的;特别是我只能在2003年找到'程序'的引用而不是90。 – 2012-03-14 19:06:41