次の方法で共有


コンテキストに依存する式と省略される式

コンテキストに依存する式とは、特定のコンテキストでのみ有効な式です。コピーと更新の式で、修飾なしで項目名を使用する場合などです。

式は、evaluate-and-reassign ステートメントの場合のように、コンパイラで推定して自動的に挿入できるときには "省略" できます。

コンテキストに依存する式と省略式の両方に適用されるもう 1 つの例として、オープン エンドの範囲があります。 これらは特定のコンテキスト内でのみ有効であり、コンパイラは、適切な境界を推論することによって、コンパイル中に通常 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 です。