Fortran が次のような一般的な構文をサポートすることを願っています
subroutine mysub( x, val = -1 )
integer, optional :: val
またはよりFortranスタイルで
subroutine mysub( x, val )
integer, optional :: val = -1 !! not SAVE attribute intended
しかし、これはサポートされていないようです (2016 年現在)。そのため、ユーザー側で何らかの回避策を講じる必要があります...
私の場合、試行錯誤の末、任意の仮引数にアンダースコアを1つ付けることに落ち着いたので、(*)のようにしました。
subroutine mysub( x, val_)
integer, optional :: val_
integer val
他の人は反対のパターンを好むようです (つまり、ダミー変数 => sep
、ローカル変数 => 。たとえば、 StringiFor のsplit() を参照)sep_
。この行に見られるように、デフォルト値を設定する最短の方法は
val = -1 ; if (present(val_)) val = val_
しかし、この行でもやや冗長なので、通常は次のようなマクロを定義します
#define optval(x,opt,val) x = val; if (present(opt)) x = opt
共通のヘッダー ファイルで、次のように使用します。
subroutine mysub( x, val_, eps_ )
integer :: x
integer, optional :: val_
real, optional :: eps_
integer val
real eps
optval( val, val_, -1 )
optval( eps, eps_, 1.0e-5 )
print *, "x=", x, "val=", val, "eps=", eps
endsubroutine
...
call mysub( 100 )
call mysub( 100, val_= 3 )
call mysub( 100, val_= 3, eps_= 1.0e-8 )
しかし、これはまだ洗練されたものではなく、(サブルーチンの本体で目的の変数名を使用することによって) エラーが発生しにくくするための努力にすぎないと思います。
非常に「大きな」サブルーチンの別の回避策は、残りのすべてのキーワード引数を含む派生型を渡すことです。例えば、
#define getkey(T) type(T), optional :: key_; type(T) key; if (present(key_)) key = key_
module mymod
implicit none
type mysub_k
integer :: val = -1
real :: eps = 1.0e-3
endtype
contains
subroutine mysub( x, seed_, key_ )
integer :: x
integer, optional :: seed_
integer :: seed
getkey(mysub_k) !! for all the remaining keyword arguments
optval( seed, seed_, 100 )
print *, x, seed, key% val, key% eps
endsubroutine
endmodule
program main
use mymod, key => mysub_k
call mysub( 10 )
call mysub( 20, key_= key( val = 3 ) )
call mysub( 30, seed_=200, key_= key( eps = 1.0e-8 ) ) ! ugly...
endprogram
これは、内部で動的言語によって行われていることに少し近いかもしれませんが、上記の形式ではエレガントとはほど遠いものです...
(*) CPP マクロを使用するのは見苦しいと見なされることが多いことは知っていますが、IMO はそれらの使用方法に依存します。それらが Fortran 構文の限られた拡張に制限されている場合、使用するのが合理的だと思います (Fortran にはメタプログラミング機能がないため)。一方、プログラム依存の定数または分岐を定義することは、おそらく避けるべきです。また、Python などを使用してより柔軟なプリプロセッサ (たとえば、PreForM.pyやfyppなど) を作成すると、より強力になると思います。たとえば、次のような構文を許可します。subroutine sub( val = -1 )