internal チュートリアル
このページは、immut や mutable に行列演算を追加し、その入力を検証する必要があるコントリビューター向けです。下流のコードは internal をインポートできず、ガードは公開メソッドを通じてしか見えません。規則は internal の設計 にあります。
クイックスタート
リポジトリの中では、moon.pkg でパッケージをインポートし、ガードをスコープに入れます。
///|
// moon.pkg
import {
"Luna-Flow/linear-algebra/internal",
}
///|
using @internal {trait HasShape, ensure_square, ensure_square_checked}
日常的なタスク
検査付き・検査なしの組を追加する
検査付きのガードで検証してから検査なし形式を呼ぶことで、検査付き・検査なしの法則が構成上成り立ちます。
///|
pub fn[T : Add + Zero] Matrix::anti_trace(
self : Matrix[T],
) -> Result[T, LinearAlgebraError] {
match ensure_square_checked(self) {
Ok(_) => Ok(self.unchecked_anti_trace())
Err(err) => Err(err)
}
}
///|
pub fn[T : Add + Zero] Matrix::unchecked_anti_trace(self : Matrix[T]) -> T {
ensure_square(self)
let n = self.row
let mut sum = Zero::zero()
for i in 0..<n {
sum = sum + self[i][n - 1 - i]
}
sum
}
アクセス時にインデックスを検査する
行を選択するときは ensure_row_in_bounds を、ストレージのオフセットを計算する前には ensure_index_in_bounds を使ってください。平坦なオフセットだけを判定してはいけません。
外部から結果を観測する
テストで固定すべきなのは公開された振る舞いです。
///|
test "the same guard in both packages" {
let i = @immut.Matrix::from_2d_array([[1, 2, 3]])
let m = @mutable.Matrix::from_2d_array([[1, 2, 3]])
let ei = match i.trace() {
Err(e) => e.message
Ok(_) => ""
}
let em = match m.trace() {
Err(e) => e.message
Ok(_) => ""
}
inspect(ei == em, content="true")
}
さらに進んで
リポジトリ内の新しい行列のような型は、HasShape を一度実装すればすべてのガードを使えます。リファクタリングの際はエラーの種類とメッセージを変えないでください。consistency のテストと下流のユーザーがそれに依存しています。
よくある落とし穴
- 検査付きメソッドで中断するガードを呼ぶ。 検査付きメソッドが
Errを返す代わりに中断してしまいます。 - 変更した後に検査する。
mutableでは、エラーで行列が変更されないよう、最初の書き込みの前に検証してください。
次のステップ
- internal API。
- 検査付き・検査なしの法則については エラーの設計。
- コントリビューションガイド。