「引数がない?それならデフォルトを!」FortranのOPTIONALで柔軟なAPI設計を極める
こんにちは。宇宙航空の現場で長年、数千億グリッドの流体シミュレーションと格闘してきた者です。
C言語やPythonからFortranの世界に足を踏み入れた皆さん、最初は「配列の添字が1から始まる」ことや「列優先(Column-major)」というメモリのクセに戸惑うかもしれません。でも大丈夫。Fortranは、実は「科学技術計算という極限環境で、安全かつ柔軟に動くこと」に特化した、非常に洗練された言語なのです。
今回は、API設計の要である`OPTIONAL`属性と`PRESENT`関数について、現場の知見を交えて解説します。
—
なぜ「引数の省略」が重要なのか?
例えば、ある物理量を計算する関数を作るとします。「基本的にはデフォルトの許容誤差(1e-6)で計算したいけれど、時々もっと厳密な(1e-10)計算が必要になる」といった状況は日常茶飯事ですよね。
Pythonなら「キーワード引数」でサクッと書けますが、Fortranではどうするのか?ここで登場するのが`OPTIONAL`です。
基本の書き方:OPTIONAL属性
まずは、引数を省略可能にするための宣言を見てみましょう。
subroutine compute_physics(data, tolerance)
implicit none
real(8), intent(in) :: data(:)
! OPTIONAL属性をつけることで「渡さなくても文句を言わない」状態にする
real(8), intent(in), optional :: tolerance
real(8) :: actual_tol
! PRESENT関数で「引数が本当に渡されたか」をチェック
if (present(tolerance)) then
actual_tol = tolerance
else
! 渡されなかった場合のデフォルト値を設定
actual_tol = 1.0e-6_8
end if
! 以下、計算処理…
end subroutine compute_physics
現場のエンジニアが教える「陥りやすい罠」
この`OPTIONAL`と`PRESENT`、実は注意すべき点が2つあります。
1. 「未定義の変数」をうっかり触らないこと
当たり前ですが、`present(tolerance)`が`.false.`のときに`tolerance`という変数名にアクセスしてはいけません。セグメンテーションフォールト(メモリ不正アクセス)の温床になります。必ず`if`文のガードの中で安全に処理してください。
2. コンパイラの最適化との関係(ここが重要!)
Fortranのコンパイラは、`OPTIONAL`引数がある場合、内部的に「ポインタ」のような仕組みを使って引数の有無を判定しています。そのため、ループの最も内側(ホットパス)で頻繁に`PRESENT`を呼ぶのは避けましょう。
もし計算速度が重要なら、以下のように「サブルーチンに入る前」にデフォルト値を確定させておくのが鉄則です。
! 悪い例:ループの数億回の中でPRESENTを呼んでいる
do i = 1, N
call process(val, opt_val) ! process内で毎回if (present)を実行
end do
! 良い例:ループに入る前に値を確定させる
actual_opt = 1.0_8
if (present(opt_val)) actual_opt = opt_val
do i = 1, N
call process_fast(val, actual_opt) ! ここは高速に回る
end do
—
インターフェースブロックの必須ルール
ここがC言語経験者が一番驚くポイントです。Fortranで`OPTIONAL`を使う場合、明示的なインターフェース(Interface Block)が必須です。
「引数が省略できる」という情報をコンパイラに事前に教えておかないと、呼び出し側でコンパイルエラーになるからです。
interface
subroutine compute_physics(data, tolerance)
real(8), intent(in) :: data(:)
real(8), intent(in), optional :: tolerance
end subroutine compute_physics
end interface
最近のモダンFortran(Fortran 90以降、特に2003/2008)では、モジュールの中にサブルーチンを記述すれば、このインターフェースは自動的に生成されます。「サブルーチンは必ずModuleの中に書く」。これを守るだけで、多くのトラブルを回避できます。
—
最後に:なぜ「泥臭い」ことが必要なのか
私が宇宙開発の現場で学んだのは、「コードの美しさ」以上に「計算の確実性」でした。
`OPTIONAL`を適切に使うことで、コードは「何が必須で、何がオプションなのか」を語り始めます。これは、数年後の自分や、あなたのコードを引き継ぐ誰かにとっての「設計図」そのものになるのです。
まずは、皆さんの手元のコードで、一番単純な引数から`OPTIONAL`に書き換えてみてください。コンパイラ(`gfortran -Wall`など)が、これまで見過ごしていた警告を教えてくれるかもしれませんよ。
もしビルド設定や最適化で詰まったら、いつでも聞いてくださいね。皆さんの研究や開発が、より速く、より正確に進むことを心から応援しています!

コメント