container/adapters 教程

本教程演示如何为仓库中的每种类型挑选合适的现成字典,并将其与 container 算法配合使用,包括 @mutable.Matrix 的实时视图。如果你想为自己的类型编写字典,请改读 container 教程。

快速上手

moon add Luna-Flow/linear-algebra@0.5.0
///|
import {
  "Luna-Flow/linear-algebra/container",
  "Luna-Flow/linear-algebra/container/adapters" @container_adapters,
  "Luna-Flow/linear-algebra/immut",
  "Luna-Flow/linear-algebra/mutable",
}

工厂函数的名称表明了类型和能力:

///|
test "read one entry through an adapter" {
  let v = @immut.Vector::from_array([10, 20, 30])
  let ops = @container_adapters.immutable_vector_read_ops()
  inspect((ops.length)(v), content="3")
  inspect((ops.get)(v, 2).unwrap(), content="30")
}

日常任务

从矩阵中复制出一行

行视图是向量源,因此任何向量目标都可以接收它:

///|
test "copy a row view into an immutable vector" {
  let m = @mutable.Matrix::from_2d_array([[1, 2, 3], [4, 5, 6]])
  let row : @immut.Vector[Int] = @container.vector_convert(
    m.row_view(1),
    @container_adapters.mutable_row_view_read_ops(),
    @container_adapters.immutable_vector_build_ops(),
  ).unwrap()
  m.set(1, 0, 40)
  inspect(row, content="|4, 5, 6|")
}

物化转置视图

@mutable.Matrix 的转置视图是矩阵源,因此 matrix_convert 可以将其物化为任意表示:

///|
test "materialize a transpose view" {
  let m = @mutable.Matrix::from_2d_array([[1, 2, 3], [4, 5, 6]])
  let t : @immut.Matrix[Int] = @container.matrix_convert(
    m.to_transpose(),
    @container_adapters.mutable_transpose_read_ops(),
    @container_adapters.immutable_matrix_build_ops(),
  ).unwrap()
  inspect(t, content="|1, 4|\n|2, 5|\n|3, 6|")
}

通过列视图写入

///|
test "clear a column through its view" {
  let m = @mutable.Matrix::from_2d_array([[1, 2], [3, 4], [5, 6]])
  let col = m.col_view(0)
  let edit = @container_adapters.mutable_col_view_mutable_edit_ops()
  for i in 0..<col.length() {
    (edit.set)(col, i, 0).unwrap()
  }
  inspect(m, content="|0, 2|\n|0, 4|\n|0, 6|")
}

在默认后端的包装类型之间搬运

///|
test "mutable dense wrapper to immutable dense wrapper" {
  let source = @default.DenseVector::from_array([1.5, 2.5])
  let target : @default.ImmutableDenseVector[Double] = @container.vector_convert(
    source,
    @container_adapters.dense_vector_read_ops(),
    @container_adapters.immutable_dense_vector_build_ops(),
  ).unwrap()
  inspect(target[1], content="2.5")
}

进一步了解

选择编辑形式。 具有值语义的类型(@immut、Immutable* 包装类型)只有 *_persistent_edit_ops;具有原地语义的类型(@mutable、视图、DenseVector、DenseMatrix)只有 *_mutable_edit_ops。进行编辑的泛型代码应接收与其所预期所有权模型相匹配的记录。

把视图作为目标。 视图没有构造字典。若要用另一个向量填充已有矩阵的一行,请读取源,并在循环中通过 mutable_row_view_mutable_edit_ops 写入。

常见陷阱

  • 以为转换结果会保持关联。 转换视图会复制;之后对矩阵的写入不会影响副本,正如复制行的示例所示。
  • 对默认包装类型使用 immutable_*。 immutable_matrix_* 适配的是 @immut.Matrix;包装类型 @default.ImmutableDenseMatrix 有自己的 immutable_dense_matrix_* 工厂函数。

后续步骤