Fortran/サブルーチンと関数
関数とサブルーチン

ほとんどのプログラムでは、同じブロックのコードが複数の場所で再利用されることがよくあります。コードの重複を最小限に抑え、コードのメンテナンスを容易にするためには、そのようなコードのブロックは関数またはサブルーチン内に配置する必要があります。Fortranのfunctionは、数学的な関数に似ており、0個以上の引数を入力として受け取り、単一の出力値を返します。Fortranのsubroutineは、入力変数に対していくつかの操作を行うコードブロックであり、サブルーチンを呼び出すことで入力変数が変更されます。
関数とサブルーチン

多くのプログラミング言語では、関数とサブルーチンを区別しません(例:C/C++、Python、Rust、Go)。純粋な関数型プログラミング言語(例:Haskell)では、サブルーチンは場合によっては入力変数を副作用として変更できるため、コードを複雑にする可能性があるため、関数のみが許可されます。
関数とサブルーチン

関数はサブルーチンよりもシンプルです。関数は単一の値を返さなければならず、write文、if (function) then内の式などの式内から呼び出すことができます。サブルーチンは値を返さず、その引数を介して多くの値を返すことができ、callキーワードを使用して単独のコマンドとしてのみ使用できます。
関数

Fortranでは、functionを使用して値または値の配列を返すことができます。次のプログラムは、整数の自乗と立方の和を計算するために関数を呼び出します。
関数

引数iのintent (in)属性は、iが関数内で変更されないことを意味し、それに対して戻り値jは自動的にintent (out)を持ちます。 funcの戻り値の型を宣言する必要があることに注意してください。これを省略すると、一部のコンパイラではコンパイルされません。 Open64(訳註:Itaniumおよびx86-64マイクロプロセッサアーキテクチャ向けの無料のオープンソースの最適化コンパイラ)は警告を伴って生成されたコードをコンパイルしますが、動作は定義されていません。
関数

別の形式(F77互換)は次のとおりです。
関数

func_nameの戻り値の型も、上記と同様に宣言する必要があります。唯一の違いは、func_name内でfunc_nameの戻り値の型が参照される方法です。この場合、戻り値変数は関数自体と同じ名前を持っています。
関数

再帰関数は、以下に示す方法で宣言でき、コードをコンパイルできるようになります。
サブルーチン

subroutineは、その引数を介して複数の値を返すために使用できます。これはcall文で呼び出されます。以下はその例です。
インテント

関数とサブルーチン内で宣言される変数に対して、渡す必要がある場合はインテント(Intent; 意図)を追加することができます。 デフォルトでは、インテントのチェックは行われず、コンパイラによって誤ったコーディングが検出されない可能性があります。
関数とサブルーチンのさらなる比較

関数は、結果のデータ型を別々の変数または関数名で定義できます。
関数とサブルーチンのさらなる比較

以下に例を示します
関数とサブルーチンのさらなる比較

手続きは、モジュールuseで含めるか、external手続きとして指定する必要があります。 externalはimplicitインターフェイスのみを提供します。これは、コンパイラが引数の数やデータ型を把握していないため、コンパイル時に警告を生成できないことを意味します(モジュールuseからの明示的インターフェイスとは対照的です。参照: Fortran/オブジェクト指向プログラミング)。
関数とサブルーチンのさらなる比較

関数とサブルーチンは、入力変数を変更できます。サブルーチンは出力値を返さないため、必然的に入力変数を変更します。関数はそうする必要はありませんが、デフォルトでは入力変数を変更することが許可されます。関数は、すべての入力変数にintent属性を使用し、さらにpureキーワードを使用して、いかなる副作用(side-effects)も持たない純粋な関数に変換できます。 pureキーワードは、実質的に関数がいかなる副作用も持たないようにする追加の制限を課します。
関数とサブルーチンのさらなる比較

pure関数の例を示します。
関数とサブルーチンのさらなる比較

を
関数とサブルーチンのさらなる比較

にコンパイラにより最適化することが可能となります。
関数とサブルーチンのさらなる比較

ダミー名で引数を指定すると、入力引数の順序を任意に指定できます。それは、呼び出し手続きが意図された手続きのインターフェイスブロックを持っている場合(moduleを使用すると自動的に作成される)、可能です。
関数とサブルーチンのさらなる比較

また、一部のパラメーターを位置で、残りのパラメーターをダミー名で指定するハイブリッドメソッドもあります。
関数とサブルーチンのさらなる比較

次に例を示します。
関数とサブルーチンのさらなる比較

引数はoptionalとして設定することができます。 組み込み関数presentを使用して、特定のパラメーターが設定されているかどうかを確認できます。
関数とサブルーチンのさらなる比較

以下に例を示します。
関数とサブルーチンのさらなる比較

手続きがダミー引数として別の手続きを持っている場合、その型を指定する必要があります。これは、procedure文とその引数の定義からなるinterfaceブロックを使用して行われます。
関数とサブルーチンのさらなる比較

注意:各interfaceブロックには独自のスコープがあります。そのため、外部の値にアクセスする必要がある場合は、明示的にそれらを読み込む必要があります。これは、importまたはuse文によって実現できます。
関数とサブルーチンのさらなる比較

以下に例を示します。
関数とサブルーチンのさらなる比較

変数の値を手続き呼び出しの間に保存するには、save属性を明示的に指定します。
関数とサブルーチンのさらなる比較

以下に例を示します。
関数とサブルーチンのさらなる比較

整数、実数、複素データ型に対して機能するabs関数のように、異なる入力引数のために同じ名前のジェネリック関数を作成することができます。
関数とサブルーチンのさらなる比較

以下の例は、整数または文字列を追加するadd関数を作成する方法を示しています。
関数とサブルーチンのさらなる比較

抽象型のタイプバウンド手続きを作成するには、deferred遅延属性を指定する必要があります。これにより、型の実際のバインディングが行われるまで、型バウンド手続きは実際には作成されません。これにより、型のバインディングポイントを決定するために、プログラムの実行時にタイプバウンド手続きを選択する柔軟性が向上します。
関数とサブルーチンのさらなる比較

詳しくはFortran/オブジェクト指向プログラミング#抽象型の項を参照してください。
要素別処理手続 (Elemental)

要素は任意の次元のパラメーターを操作する手続きを作成することができます。キーワード elemental は、単一のオブジェクト(例:整数)に対する操作を定義する場合に使用され、一般的な場合は自動的に処理されます。
要素別処理手続 (Elemental)

以下の例は、任意の長さの整数次元の加算が示されています。