不変性
Q# でのすべての型は "値の型" です。
Q# には、参照またはポインターの概念がありません。 代わりに、set
ステートメントを使用して、前に宣言された変数に新しい値を再割り当てすることができます。 たとえば、再割り当て (たとえば、型 Int
の変数または型 Int[]
の変数) の間に動作の区別はありません。 次のような一連のステートメントについて考えてみます。
mutable arr1 = new Int[3];
let arr2 = arr1;
set arr1 w/= 0 <- 3;
最初のステートメントでは、整数 [0,0,0]
の新しい配列をインスタンス化し、それを arr1
に割り当てます。
次のステートメントでは、その値を arr2
という名前の変数に割り当てます。 最後のステートメントでは、3 に設定されているインデックス 0 の値を除き同じ値を使用して、arr1
に基づく新しい配列インスタンスを作成します。 新しく作成された配列は、その後、変数 arr1
に割り当てられます。 最後の行は、evaluate-and-reassign ステートメントの省略された構文を使用しており、同等に set arr1 = arr1 w/ 0 <- 1;
と記述することもできます。
これらの 3 つのステートメントを実行すると、arr1
には値 [3,0,0]
が含まれるのに対して、arr2
は変更されないままで [0,0,0]
が含まれます。
Q# では、このように、ハンドルの変更可能性と型の動作を明確に区別します。 Q# 内の変更可能性は、型または値ではなく、"シンボル" に適用される概念です。これは、値自体にではなく、その値へのアクセスを可能にするハンドルに適用されます。 これは、暗黙的にも明示的にも、型システムでは表され "ません"。
もちろん、これは、正式に定義されている動作の説明にすぎません。内部では、メモリのコピーをできるだけ回避するために、実際の実装によって参照カウント スキームが使用されます。 特に、特定の値にアクセスする現在有効なハンドルが 1 つだけである限り、変更はインプレースで実行されます。