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

上下文和省略的表达式

上下文表达式是仅在某些上下文中有效的表达式,例如 copy-and-update 表达式中的项名称的使用,而无需限定它们。

在编译器推理和自动插入表达式时可以省略表达式,例如在 evaluate-and-reassign 语句中。

开放式范围是适用于上下文表达式和省略表达式的另一个示例。 它们仅在特定上下文中有效,编译器通过推断合适的边界在编译过程中将它们转换为普通 Range 表达式。

Range 类型的值生成一个整数序列,由开始值、步长值(可选)和结束值指定。 例如,Range 文本表达式 1..3 生成序列 1,2,3。 同样地,表达式 3..-1..1 生成序列 3,2,1。 还可以使用范围通过切片从一个现有数组创建新的数组,例如:

    let arr = [1,2,3,4];
    let slice1 = arr[1..2..4];  // contains [2,4] 
    let slice2 = arr[2..-1..0]; // contains [3,2,1]

不能在 Q# 中定义无限范围;始终需要指定开始值和结束值。 唯一的例外是使用 Range 对数组进行切片时。 在这种情况下,编译器可以合理地推理出范围的开始值或结束值。

在之前的数组切片示例中,如果步长为正,则编译器可以合理地假设预期的范围结束值应该是数组中最后一项的索引。 如果步长为负数,则范围结束可能应该是数组 0 中的第一个项的索引。 范围的开始则相反。

总而言之,如果省略范围起始值,则推理的开始值

  • 为 0(如果未指定步长或指定的步长为正)。
  • 为数组的长度减 1(如果指定的步长为负)。

如果省略范围结束值,则推理的结束值

  • 为数组的长度减 1(如果未指定步长或指定的步长为正)。
  • 为 0(如果指定的步长为负)。

因此 Q# 允许在数组切片表达式内使用无限制范围,例如:

let arr = [1,2,3,4,5,6];
let slice1  = arr[3...];      // slice1 is [4,5,6];
let slice2  = arr[0..2...];   // slice2 is [1,3,5];
let slice3  = arr[...2];      // slice3 is [1,2,3];
let slice4  = arr[...2..3];   // slice4 is [1,3];
let slice5  = arr[...2...];   // slice5 is [1,3,5];
let slice7  = arr[4..-2...];  // slice7 is [5,3,1];
let slice8  = arr[...-1..3];  // slice8 is [6,5,4];
let slice9  = arr[...-1...];  // slice9 is [6,5,4,3,2,1];
let slice10 = arr[...];       // slice10 is [1,2,3,4,5,6];

由于确定范围步长是正还是负发生在运行时,因此编译器会插入一个在在运行时求值的适当表达式。 对于省略的结束值,插入的表达式为 step < 0 ? 0 | Length(arr)-1;对于省略的开始值,该表达式为 step < 0 ? Length(arr)-1 | 0,其中 step 是为范围步长指定的表达式,如果未指定步长,则为 1