你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

变量声明和重新赋值

可通过 letmutable 语句将值绑定到符号。 这些类型的绑定提供了一种通过定义的句柄访问值的便捷方法。 尽管从其他语言借用了存在误导性的术语,但在局部范围声明并包含值的句柄被称为“变量”。 这可能具有误导性,因为 let 语句定义单赋值句柄,它们再有效期内始终绑定到相同的值。 可在代码中的不同点重新绑定到不同值的变量需要以这种方式显式声明,并且使用 mutable 语句进行了指定。

    let var1 = 3; 
    mutable var2 = 3; 
    set var2 = var2 + 1; 

在此示例中,let 语句声明一个名为 var1 的变量,该变量无法重新分配,并且将始终包含值 3mutable 定义一个变量 var2,该变量临时绑定到值 3,但之后可使用 set 语句重新分配给其他值,如最后一行所示。 可使用简写版 set var2 += 1; 表达同一个语句,这在其他语言中很常见。 有关详细信息,请参阅求值和重新赋值语句

总结:

  • let 用于创建不可变的绑定。
  • mutable 用于创建可变的绑定。
  • set 用于更改可变绑定的值。

对于这三个语句,左侧包含一个符号和一个符号元组。 如果绑定的右侧是一个元组,则该元组可能会在赋值时完全或部分析构。 析构的唯一要求是右侧元组的形状与左侧符号元组的形状匹配。 符号元组可能包含嵌套元组和/或省略的符号,用下划线指示。 例如:

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]
set (x, _, y) = ((5, 6), 7, [8]);  // x is re-bound to (5,6), y is re-bound to [8]

Q# 中的所有赋值都遵循相同的析构规则,例如,量子比特分配和循环变量赋值。

对于这两种类型的绑定,变量的类型是从绑定的右侧推断出来的。 变量的类型始终保持不变,并且 set 语句无法更改它。 局部变量可声明为可变或不可变。 存在一些意外情况,例如 for 循环中的循环变量;在这类循环中,行为是预定义的且无法指定。 函数和操作参数的绑定始终是不可变的。 加上缺少引用类型,如不可变性主体中所述,这意味着被调用的函数或运算永远不会更改调用方端的任何值。

由于 Qubit 值的状态并非从 Q# 内部定义或在其内部不可观测,因此这并不排除量子副作用的积累,这些副作用仅可通过测量观察到。 有关详细信息,请参阅 Quantum 数据类型

与值的绑定方式无关,值本身是不可变的。 这一点特别适用于数组和数组项。 与数组通常是引用类型的常用经典语言不同,Q# 中的数组(与所有类型一样)是值类型,并且始终不可变;也就是说,初始化后无法修改。 因此,访问数组类型变量访问的值需要显式构造新的数组并将该数组重新分配给同一符号。 有关详细信息,请参阅不可变性复制和更新表达式

求值和重新赋值语句

set intValue += 1; 形式的语句在许多其他语言中很常见。 此处,intValue 需要成为类型 Int 的可变绑定变量。 如果右侧由二元运算符的应用组成,并且将结果重新绑定到运算符的左侧参数,则此类语句可提供一种方便的串联方式。 例如,此代码段

mutable counter = 0;
for i in 1 .. 2 .. 10 {
    set counter += 1;
    // ...
}

递增 for 循环的每次迭代中计数器 counter 的值,并且等效于

mutable counter = 0;
for i in 1 .. 2 .. 10 {
    set counter = counter + 1;
    // ...
}

类似的语句适用于各种运算符。 在此类求值和重新赋值语句中,set 关键字后面必须跟一个可变变量,编译器将其作为最左侧的子表达式插入。 对于最左侧子表达式的类型与表达式类型匹配的所有运算符,都存在此类计算和重新赋值语句。 更确切地说,它们可用于二进制逻辑和按位运算符(包括右移和左移位)、算术表达式(包括幂和取模)、串联以及复制和更新表达式

以下函数示例计算 Complex 数字数组的总和:

function ComplexSum(values : Complex[]) : Complex {
    mutable res = Complex(0., 0.);
    for complex in values {
        set res w/= Re <- res::Re + complex::Re;
        set res w/= 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) {
        set res w/= i <- factor * array[i];
    }
    return res;
}

有关详细信息,请参阅上下文表达式,该文章包含其他示例,其中当编译器可推断出合适的表达式时,可在特定上下文中省略表达式。