モジュールとプログラム#
モジュールは、最新のFortranライブラリとアプリケーションを作成するための推奨される方法です。慣例として、1つのソースファイルには常に1つのモジュールのみを含める必要があり、モジュール名はファイルパスと一致する必要があります。大規模なプロジェクトで簡単にナビゲーションできるようにするためです。また、他のプロジェクトで依存関係として使用する場合の名前の衝突を避けるために、モジュール名の先頭にライブラリ名を付けることをお勧めします。
このようなモジュールファイルの例を次に示します。
!> Interface to TOML processing library.
!>
!> ...
module fpm_toml
use fpm_error, only : error_t, fatal_error, file_not_found_error
use fpm_strings, only : string_t
use tomlf, only : toml_table, toml_array, toml_key, toml_stat, get_value, &
& set_value, toml_parse, toml_error, new_table, add_table, add_array, &
& toml_serializer, len
implicit none
private
public :: read_package_file
public :: toml_table, toml_array, toml_key, toml_stat, get_value, set_value
public :: new_table, add_table, add_array, len
public :: toml_error, toml_serializer, toml_parse
contains
!> Process the configuration file to a TOML data structure
subroutine read_package_file(table, manifest, error)
!> TOML data structure
type(toml_table), allocatable, intent(out) :: table
!> Name of the package configuration file
character(len=*), intent(in) :: manifest
!> Error status of the operation
type(error_t), allocatable, intent(out) :: error
! ...
end subroutine read_package_file
end module fpm_toml
このモジュール例には、強調すべき点がいくつかあります。まず、すべてのモジュールは、モジュールの目的と内容を説明するコメントで始まります。同様に、すべての手続きは、その目的と仮引数の意図を簡単に説明するコメントで始まります。ドキュメントは、言語に関係なく、長寿命のソフトウェアを作成する上で最も重要な部分の1つです。
次に、インポート(use)とエクスポート(public)が明示的に指定されています。これにより、モジュールソースを一目で確認して、使用されている手続き、定数、および派生型を確認できます。インポートは通常、すべての手続きまたはインターフェーススコープで再インポートされるのではなく、モジュールスコープに制限されます。同様に、エクスポートは、1行にprivateステートメントを追加し、publicステートメントにすべてのエクスポートされたシンボルを明示的にリストすることによって明示的に行われます。
最後に、implicit none
ステートメントはモジュール全体で機能し、各手続き内で繰り返す必要はありません。
モジュール内の変数は静的です(暗黙的に保存されます)。モジュール変数の使用は、パラメータや列挙子などの定数式に限定するか、publicではなくprotectedとしてエクスポートすることを強くお勧めします。
サブモジュールを使用すると、長い依存関係チェーンを分割し、Fortranプログラムの再コンパイルカスケードを短縮できます。また、プリプロセッサを使用せずに、特殊化された最適化された実装を提供する可能性も提供します。
Fortran標準ライブラリの例は、モジュール手続きへのインターフェースのみを定義し、実装は定義しない求積法モジュールです。
!> Numerical integration
!>
!> ...
module stdlib_quadrature
use stdlib_kinds, only: sp, dp, qp
implicit none
private
public :: trapz
! ...
!> Integrates sampled values using trapezoidal rule
interface trapz
pure module function trapz_dx_dp(y, dx) result(integral)
real(dp), intent(in) :: y(:)
real(dp), intent(in) :: dx
real(dp) :: integral
end function trapz_dx_dp
module function trapz_x_dp(y, x) result(integral)
real(dp), intent(in) :: y(:)
real(dp), intent(in) :: x(:)
real(dp) :: integral
end function trapz_x_dp
end interface trapz
! ...
end module stdlib_quadrature
実装は、ここに示す台形積分則のような個別のサブモジュールで提供されます。
!> Actual implementation of the trapezoidal integration rule
!>
!> ...
submodule (stdlib_quadrature) stdlib_quadrature_trapz
use stdlib_error, only: check
implicit none
contains
pure module function trapz_dx_dp(y, dx) result(integral)
real(dp), intent(in) :: y(:)
real(dp), intent(in) :: dx
real(dp) :: integral
integer :: n
n = size(y)
select case (n)
case (0:1)
integral = 0.0_dp
case (2)
integral = 0.5_dp*dx*(y(1) + y(2))
case default
integral = dx*(sum(y(2:n-1)) + 0.5_dp*(y(1) + y(n)))
end select
end function trapz_dx_dp
! ...
end submodule stdlib_quadrature_trapz
モジュール手続きは同じサブモジュールに実装する必要はないことに注意してください。巨大なモジュールのコンパイル負荷を軽減するために、複数のサブモジュールを使用できます。
最後に、プログラムを設定する場合、プログラム本体の実際の実装を最小限に抑えることをお勧めします。モジュールの実装を再利用することで、再利用可能なコードを作成し、プログラムユニットをそれぞれのライブラリ関数とオブジェクトへのユーザー入力の伝達に集中させることができます。