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。
- 错误设计:受检/非受检定律。
- 贡献指南。