1

関数を別の関数にf1(f2(k, g, x), other, junk)(f1として定義されf1(func, other, junk)、 のような式を含むfunc(other)) で渡したいとします。さらに、これらの関数の両方が 3 番目の関数に含まれているとしますf3(k, g)f3(k, g)と のいくつかの値でk呼び出すことによって、実際にはもはや 3 つの変数の関数gf2はないでしょうか? xそれはそれ以来の関数でkあり、g現在は定数です。だから私が知りたいのは、どういうわけか言い方があるかどうかというf2ことです。の関数として、私があなたをに渡すときkgf3xf1、変数が 1 つだけの関数を見て使用します。」

4

2 に答える 2

0

あなたが探していると思うのは、「ファンクター/関数オブジェクト」またはラムダ式と呼ばれることがあります-いくつかの引数を持つプロシージャを、より少ない引数で呼び出すことができる方法でラップする機能(不足している引数が指定されています)他の手段で)。

Fortran 77 では、これは通常、「不足している」引数を共通ブロックの舞台裏で渡すことによって概算されていました。Fortran 90/95 では、モジュール変数を使用できるようにすることで、これを変更しました。これらのアプローチには両方とも、一度に存在できるラップされたプロシージャのインスタンスが 1 つだけであるという欠点がありますが、共通ブロックに対するモジュールの使用は、他の理由から非常に優れたオプションです。

Fortran 2003 では、派生型と型拡張を使用する他のオプションが導入されています。これには、f1 のコードを変更する必要があります。仮の手続き引数を持つ代わりに、関数は多態的な引数を取ります。その宣言された型には、f1 の前の引数と同様のインターフェイスを持つが渡されたオブジェクトを持つバインディングがあります。不足している引数は、その宣言された型の拡張機能のコンポーネントになります。このアプローチにより、柔軟性と機能が大幅に向上します。特に、ラップされたプロシージャの複数のインスタンスを一度に存在させることができますが、多少の冗長性が犠牲になります。

Fortran 2008 では、内部プロシージャを使用する別のオプションが導入されています。欠落している引数は、ホスト プロシージャから内部プロシージャへのホスト関連付けを介して渡されます。(内部プロシージャーを実際のプロシージャー引数として渡すことが許可されていなかったため、このアプローチは以前の標準では使用できませんでした)。プロシージャー・ポインターを使用して、ラップされたプロシージャーの複数のインスタンスを存続させることができます。

添付の 4 つの異なるアプローチの例。otherF3 プロシージャのどの例でもandエンティティが宣言されていないことに注意してください。junkまた、例のためにいくつかの他の省略 (または非常に貧弱なプログラミング スタイルと見なされるもの) がある可能性があります。さらに、4 つのアプローチは、コードの柔軟性と堅牢性 (プログラマーのエラーがキャッチされる可能性など) の点で大きく異なることに注意してください。

C*******************************************************************************
C FORTRAN 77
      FUNCTION F1(FUNC,OTHER,JUNK)
        F1=FUNC(OTHER)+JUNK
      END FUNCTION F1
C
      FUNCTION F2(K,G,X)
        F2=K+G+X
      END FUNCTION F2
C
      FUNCTION F3(K,G)
        COMMON /F2COM/KC,GC
        KC=K
        GC=G
        F3=F1(F2WRAP,OTHER,JUNK)
      END FUNCTION F3
C
      FUNCTION F2WRAP(X)
        COMMON /F2COM/KC,GC
        F2WRAP=F2(KC,GC,X)
      END FUNCTION F2WRAP


!*******************************************************************************
! Fortran 90/95
MODULE m1990
  IMPLICIT NONE
  INTEGER :: km
  REAL :: gm
CONTAINS
  FUNCTION F2Wrap(x)
    REAL :: x
    !****
    ! F2 unchanged from F77, though good practice would be to make 
    ! it (and F1 and F3) module procedures.
    ! ensure it had an explicit interface here.
    F2Wrap = F2(km,gm,x)
  END FUNCTION F2Wrap
END MODULE m1990

FUNCTION F3(k,g)
  USE m1990
  IMPLICIT NONE
  INTEGER :: k
  REAL :: g, F3
  !****
  km = k
  gm = g
  ! F1 unchanged from F77.
  F3=F1(F2Wrap, other, junk)
END FUNCTION F3


!*******************************************************************************
! Fortran 2003
MODULE m2003
  IMPLICIT NONE
  TYPE Functor
  CONTAINS
    PROCEDURE(fun_intf), DEFERRED :: fun
  END TYPE Functor

  ABSTRACT INTERFACE
    FUNCTION fun_intf(f,x)
      IMPLICIT NONE
      IMPORT :: Functor
      CLASS(Functor), INTENT(IN) :: f
      REAL :: x, fun_intf
    END FUNCTION fun_intf
  END INTERFACE

  TYPE F2Functor
    INTEGER :: k
    REAL : g
  CONTAINS
    PROCEDURE :: fun => F2_wrap
  END TYPE F2Functor
CONTAINS
  FUNCTION F2_wrap(f,x)
    CLASS(F2Functor), INTENT(IN) :: f
    REAL :: F2_wrap, x
    ! F2 unchanged from F77
    F2_wrap = F2(f%k, f%g, x)
  END FUNCTION f2_wrap

  ! F1 modified.  Now takes a polymorphic argument in-place of the 
  ! dummy procedure - explicit interface REQUIRED.
  FUNCTION F1(f, other, junk)
    CLASS(Functor), INTENT(IN) :: f
    REAL :: F1, other
    INTEGER :: junk
    F1 = f%fun(other) + junk
  END FUNCTION 
END MODULE m2003

! Good practice would make this a module procedure.
FUNCTION f3(k,g)
  USE m2003
  IMPLICIT NONE
  TYPE(F2Functor) :: f
  REAL F3, g
  INTEGER :: k
  !****
  f%k = k
  f%g = g
  F3 = F1(f, other, junk)
END FUNCTION f3


!*******************************************************************************
! Fortran 2008 (use of procedure pointers not illustrated).

! Should be a module proc, etc...
FUNCTION F3(k,g)
  REAL :: F3, g
  INTEGER :: k
  INTEGER :: k_host
  REAL :: g_host
  k_host = k
  g_host = g
  ! F1 unchanged from F77 (though good practice is..., etc) 
  F3 = F1(F2Wrap, other, junk)
CONTAINS
  FUNCTION F2Wrap(x)
    REAL :: x, F2Wrap
    ! F2 unchanged from F77.
    F2Wrap = F2(k_host, g_host, x)
  END FUNCTION F2Wrap
END FUNCTION F3
于 2013-09-26T04:18:41.690 に答える