Динамическое создание функции из другой функции - PullRequest
4 голосов
/ 14 марта 2012

У меня есть подпрограмма 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' в глобальный или присвоить его глобальной функции.

У кого-нибудь есть идеи, как это сделать?Решение может быть таким хакерским, как вы хотите.

Ответы [ 2 ]

5 голосов
/ 14 марта 2012

Это не так просто. В некоторых языках вы можете передавать указатели на вложенные функции в так называемом closure. Это невозможно в Фортране (или Си и подобных языках), потому что данные уничтожаются с помощью стека высшей функции. Я бы предложил вам попробовать функциональные объекты, то есть class с function pointer (или более) и данные, необходимые для функции. Таким образом, вы можете даже создавать функциональные композиции и подобные функциональные вещи.

Подробнее о концепции 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
2 голосов
/ 14 марта 2012

Вы можете многое сделать с помощью указателей процедур, создав функцию, которая является комбинацией других функций. См. Массивы указателей на функции в Fortran для примера кода.

...