问题
I have a Fortran 90 subroutine which takes a function as an argument, and I would like to pass a modified version of that function into another subroutine. I want the program to look something like this:
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
I've managed to do something similar when 'g' only needs to use normal variables, not a function. In that case I made it a global function, using global variables, and assigned to those global variables in 'foo'. However, I can't find a way to turn 'f' global, or assign it to a global function.
Anybody have any ideas how to do this? The solution can be as hacky as you want.
回答1:
This is not so easy. In some languages you can pass pointers to nested functions in a so called closure
. This is not possible in Fortran (or C and similar languages), because the data are destroyed with the stack of the higher function. I would suggest you to try function objects, i.e. a class
with a function pointer
(or more) and data needed for the function. In this way you can even do function composition and similar functional stuff.
More on the concept http://en.wikipedia.org/wiki/Function_object
Below is a sample for a function object for composition of two single argument functions:
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
回答2:
You could do a lot with procedure pointers, constructing a function that is a combination of other functions. See Function pointer arrays in Fortran for a code example.
来源:https://stackoverflow.com/questions/9692697/dynamic-function-creation-from-another-function