変数宣言と再割り当て
let
ステートメントと mutable
ステートメントを使用して、値をシンボルにバインドできます。
これらの種類のバインディングは、定義されたハンドルを介して値にアクセスする便利な方法を提供します。
他の言語から借用された誤解を招く用語にもかかわらず、ローカルスコープで宣言され、値を含むハンドルは変数 let
ステートメント 単一割り当てハンドルを定義するため、誤解を招く可能性があります。これは、有効期間中、同じ値にバインドされたままのハンドルです。 コード内のさまざまなポイントで異なる値に再バインドできる変数は、明示的に宣言する必要があり、mutable
ステートメントを使用して指定します。
let var1 = 3;
mutable var2 = 3;
var2 = var2 + 1;
この例では、let
ステートメントは、再割り当てできない var1
という名前の変数を宣言し、常に 3
値を含みます。
mutable
ステートメントは、3
値に一時的にバインドされる変数 var2
を定義しますが、最後の行に示すように、代入式を使用すると後で別の値に再割り当てできます。 他の言語で一般的なのと同様に、短いバージョンの var2 += 1;
で同じステートメントを表現できます。 詳細については、「ステートメントの評価と再割り当てを行う」を参照してください。
要約すると、次のようになります。
-
let
は、変更できないバインディングを作成するために使用されます。 -
mutable
は、変更可能なバインドを作成するために使用されます。 -
let
のない=
は、変更可能なバインディングの値を変更するために使用されます。
3 つのステートメントすべてについて、左側はシンボルまたはシンボルタプルで構成されます。 バインディングの右側がタプルの場合、そのタプルは割り当て時に完全または部分的に分解される可能性があります。 分解の唯一の要件は、右側のタプルの形状が左側のシンボルタプルの形状と一致することです。 シンボルタプルには、入れ子になったタプルまたは省略されたシンボル、またはその両方がアンダースコアで示されている場合があります。 例えば:
let (a, (_, b)) = (1, (2, 3)); // a is bound to 1, b is bound to 3
mutable (x, y) = ((1, 2), [3, 4]); // x is bound to (1, 2), y is bound to [3, 4]
(x, _, y) = ((5, 6), 7, [8]); // x is re-bound to (5,6), y is re-bound to [8]
unwrap (!
) 演算子を使用した分解の詳細については、「構造体型の Item アクセス」を参照してください。
Q# のすべての代入は、量子ビットの割り当てやループ変数の割り当てなど、同じ分解規則に従います。
どちらの種類のバインディングでも、変数の型はバインディングの右側から推論されます。 変数の型は常に同じままであり、代入式では変更できません。
ローカル変数は、変更可能または不変として宣言できます。
for
ループ内のループ変数など、いくつかの例外があります。この場合、動作は定義済みであり、指定できません。
関数と操作の引数は常に不変バインドされます。
不変 トピックで説明されているように、参照型の不足と組み合わせて使用すると、呼び出された関数または操作で呼び出し元側の値を変更することはできません。
Qubit
値の状態は Q#内から定義または観測できないため、量子副作用の蓄積は妨げず、測定によってのみ観測できます。 詳細については、「Quantum データ型の」を参照してください。
値のバインド方法とは無関係に、値自体は不変です。 特に、これは配列と配列項目に当てはまります。 配列が参照型であることが多い一般的な古典的言語とは対照的に、Q# 内の配列 (すべての型と同様) は値型であり、常に不変です。つまり、初期化後に変更することはできません。 したがって、配列型変数によってアクセスされる値を変更するには、新しい配列を明示的に構築し、それを同じシンボルに再割り当てする必要があります。 詳細については、「不変の と のコピーと更新の式を参照してください。
Evaluate-and-reassign ステートメント
intValue += 1;
形式のステートメントは、他の多くの言語で一般的です。 ここでは、intValue
は、Int
型の可変にバインドされた変数である必要があります。
このようなステートメントは、右側が 2 項演算子の適用で構成され、結果が演算子の左引数にリバインドされる場合に、連結の便利な方法を提供します。
たとえば、このコード セグメント
mutable counter = 0;
for i in 1 .. 2 .. 10 {
counter += 1;
// ...
}
は、for
ループの各反復で counter
カウンターの値をインクリメントし、次の値に相当します。
mutable counter = 0;
for i in 1 .. 2 .. 10 {
counter = counter + 1;
// ...
}
同様のステートメントは、
次の関数の例では、Complex
数値の配列の合計を計算します。
function ComplexSum(values : Complex[]) : Complex {
mutable res = Complex(0., 0.);
for complex in values {
res = new Complex { Re = res.Re + complex.Re, Im = res.Im + complex.Im };
}
return res;
}
同様に、次の関数は、配列内の各項目に特定の係数を乗算します。
function Multiplied(factor : Double, array : Double[]) : Double[] {
mutable res = new Double[Length(array)];
for i in IndexRange(res) {
res w/= i <- factor * array[i];
}
return res;
}
詳細については、「コンテキスト式」を参照してください。この例には、コンパイラによって適切な式を推論できる場合に、特定のコンテキストで式を省略できるその他の例が含まれています。