mutable/context の設計
設計目標
ミュータブルな ContextPolynomial[A] は、コンテキスト、名前付き評価、代入を二重に実装することなく、名前付き変数の多項式に他のミュータブルなコンテナと同じインプレースのインターフェース(add_inplace、mul_inplace、clear、copy)を与えます。
数学的背景
セマンティクスは immut/context と同じです。 であるペア 、環準同型 としての代入、スカラーによる代入としての部分評価です。ミュータブルなコンテキスト多項式は、このようなペアを値とする変数です。インプレース演算は、固定された環 の中での代入 および です。
設計上の判断
イミュータブルな値を包むミュータブルなセル
選択。 この型は、immut/context の多項式を保持するミュータブルなフィールドを 1 つ持つレコードです。すべての問い合わせ、評価、代入は保持している値に転送されます。add_inplace、mul_inplace、clear は新しいイミュータブルな値を計算してフィールドに格納します。
理由。 コンテキストの扱いは、このライブラリで最も多くの検証規則(所属、重複、名前解決、コンテキストの等価性)を持ちます。これらを一度だけ実装することで、両層がまったく同じ呼び出しを受理・拒否し、同じ正規形の結果を生成することが保証されます。保持する値はイミュータブルなので、共有しても安全です。
copyは です。新しいセルは同じイミュータブルな値を保持し、後でどちらかのセルにインプレース演算を行っても、そのセルの値が置き換わるだけで、もう一方には影響しません。- 同じ理由で、
to_immutは保持している値をコピーせずに返し、from_immutは値をコピーせずに包みます。
独立した代入のペイロード
ContextSubstitutionValue はここで再定義されており、Polynomial(p) が ミュータブルな コンテキスト多項式を運べるようになっています。代入は、保持している値を読み取って各ペイロードをイミュータブルなものに変換してから委譲します。結果は新しいミュータブルなセルであり、代入や部分評価によってレシーバが変更されることはありません。
追加するのは二項のインプレース演算だけ
インプレース演算は add_inplace、mul_inplace、clear です。代入と部分評価はイミュータブルな API に合わせて新しいセルを返します。代入の結果は古い多項式の更新ではなく別の多項式だからです。ミュータブルな型には add_checked や mul_checked メソッドはありません。チェック付き版は ops() または to_immut() を通じて利用できます。
クリアしてもコンテキストは保たれる
clear は値を 同じ コンテキスト上の零多項式に設定し、疎な形式で格納します。コンテナは にとどまるので、その後 上の多項式で add_inplace を呼び出しても有効なままです。
正しさ / 不変条件
- immut と同じセマンティクス。 変更を伴わないすべてのメソッドは
from_immut(self.to_immut().op(...))を返します。 - コンテキストは固定。 インプレース演算はコンテキストが異なると中断するので、セルのコンテキストが変わることはありません。
- 分離。 あるセルを変更しても、他のセルや
to_immutで得たイミュータブルな値が変わることはありません。 - コスト はイミュータブルな演算のコストと同じです。
copy、from_immut、to_immutは です。
採用しなかった代替案
- ミュータブルな term と sparse のコンテナ上での ミュータブルな再実装 は、真のインプレースな項の更新を可能にしますが、すべての検証規則を重複させてしまいます。
- 変更を伴う代入(
substitute_inplace)は提供していません。代入は値に適用される準同型であり、その結果を代入し直すのは 1 行で済みます。
境界
- 項単位のインプレース更新はありません。それには
to_sparse_polynomial()で変換し、結果を再び束縛してください。 - 型自体にはチェック付きの二項演算メソッドはありません。
from_term_polynomialとfrom_sparse_polynomialのアリティが検査されないことを含め、immut/context の制約 がすべて当てはまります。