mutable チュートリアル
このチュートリアルは、多項式をその場で更新するための入口です。必要な 1 つのインポート、変更操作と演算子の違い、ミュータブル層とイミュータブル層の間の行き来、そして各表現のチュートリアルの続きがどこにあるかを示します。
クイックスタート
moon add Luna-Flow/luna-poly@0.2.0
import {
"Luna-Flow/luna-poly/mutable",
}
test "mutable quick start" {
let p = @mutable.DensePolynomial::from_coefficients([1, 2, 3])
let snapshot = p.copy()
p.set_coefficient(1, 5)
p.add_inplace(@mutable.DensePolynomial::from_coefficients([-1, -5, -3]))
assert_true(p.is_zero())
inspect(snapshot, content="1 + 2x^1 + 3x^2")
}
set_coefficient と add_inplace は p を変更します。その前に取ったコピーは影響を受けません。
日常的なタスク
コンテナを選ぶ
| やりたいこと | 使う型 | チュートリアル |
|---|---|---|
| 一変数の係数を設定・累積する | DensePolynomial | mutable/dense |
| 追加しながら多変数の項を整列状態に保つ | TermPolynomial | mutable/term |
| 多変数の項を で追加・設定する | SparsePolynomial | mutable/sparse |
| 名前付き変数の多項式を累積する | ContextPolynomial | mutable/context |
何が変更を行うかを把握する
_inplace で終わるメソッド、セッター、clear は変更を行います。演算子は決して変更を行いません:
test "what mutates" {
let p = @mutable.SparsePolynomial::from_array([([1U], 1)])
let q = p * p
inspect(p, content="1 * x")
p.mul_inplace(p)
inspect(p, content="1 * x^2")
assert_true(p == q)
}
immut との境界を越える
呼び出し側が値を受け取れるよう、モジュール境界で変換します:
fn build_power_sum(n : Int) -> @immut.DensePolynomial[Int] {
let acc : @mutable.DensePolynomial[Int] = @mutable.DensePolynomial::zero()
for k in 0..<n {
acc.set_coefficient(k, 1)
}
acc.to_immut()
}
test "boundary" {
inspect(build_power_sum(4), content="1 + 1x^1 + 1x^2 + 1x^3")
}
さらに進む
両方の層に対応するジェネリックなコード
能力トレイトと演算レコードは両方のファサードで共通です:
fn[P, A] eval_square(ops : @mutable.UnivariateOps[P, A], p : P, a : A) -> A {
ops.eval(ops.mul(p, p), a)
}
test "both layers" {
inspect(eval_square(@mutable.DensePolynomial::ops(), @mutable.DensePolynomial::from_coefficients([1, 1]), 2), content="9")
inspect(eval_square(@immut.DensePolynomial::ops(), @immut.DensePolynomial::from_coefficients([1, 1]), 2), content="9")
}
バッファをジェネリックにリセットする
すべてのミュータブルなコンテナは MutablePolynomial (Clearable + Copyable) を実装しています:
fn[P : @mutable.MutablePolynomial] fresh_copy_and_clear(p : P) -> P {
let c = @mutable.Copyable::copy(p)
@mutable.Clearable::clear(p)
c
}
test "generic reset" {
let t = @mutable.TermPolynomial::from_array([([2U], 1)])
inspect(fresh_copy_and_clear(t), content="1 * x^2")
assert_true(t.is_zero())
}
よくある落とし穴
- 束縛はコンテナを共有する.
let q = pはコピーしません。p.copy()を使ってください。 - 項配列への大量の加算.
TermPolynomial::add_inplaceは項を 1 つずつ挿入します。累積には疎なコンテナを選んでください。 - コンテキストの不一致は中断 (abort) する.
add_inplaceとmul_inplaceで起こります。チェック付きのその場更新の形式はありません。 - 層の混在.
@mutable.DensePolynomialは@immut.DensePolynomialではありません。to_immut/from_immutで変換してください。
次のステップ
- 上でリンクした各コンテナのチュートリアル。
- mutable API と mutable の設計。後者には
immutとの相違点がすべて列挙されています。 - 値指向の層については immut チュートリアル。