internal の設計
設計目標
immut と mutable は同じ前提条件(正方性、範囲、形状の適合性)を検査し、それらを同じように報告しなければなりません。internal は各検査の実装を 1 つだけ持つことで、2 つのパッケージが食い違わないようにしつつ、ヘルパーを下流のコードには公開しません。
数学的背景
各ガードは、エラーの設計 で述べた定義域の特性判定です。、 などです。判定を全域関数 として一度だけ書けば、部分演算の両方の形式が得られます。
中断するガードを検査付きのガードから導出する(ensure_x は ensure_x_checked に対してマッチする)ことで、両者は構成上あらゆる入力で一致します。
設計上の判断
internal パッケージ
MoonBit の internal パッケージ規則により、Luna-Flow/linear-algebra/internal をインポートできるのはこのモジュールのパッケージに限られます。そのためヘルパーは自由に変更でき、その効果は公開メソッドの側で規定されます。
MatrixShape とは別の HasShape
@algebra.MatrixShape も同じメソッドを持ちますが、algebra は実験的であり、具体的なパッケージはそれに依存すべきではありません。HasShape はガードに、immut と mutable がローカルに実装する境界を与えます。この重複は、安定した具体的パッケージを実験的な層から独立させておくための代償です。
列より先に行
ensure_index_in_bounds はまず行を、次に列を、それぞれ自身の次元に対して検査します。代わりに平坦なオフセット を と比較すると、次の行にはみ出す列インデックスを受け入れてしまいます。
正しさと不変条件
ensure_x(m)が中断するのは、ensure_x_checked(m)がErrを返すとき、かつそのときに限ります。- 各検査付きガードは、API ページ に挙げたエラーの種類を固定のメッセージとともに返します。
- すべてのガードは で実行され、
shapeしか呼び出しません。
却下した代替案
- 各パッケージで検査を重複させる。
0.4系より前は、これが原因で範囲外の扱いが食い違っていました。 - 公開ヘルパー。 下流のコードが依存する API になってしまいます。
境界
internal は形状とインデックスだけを検査します。算術、ストレージ、値に依存する検査(特異性、データが空であること、収束)は含みません。