Контекстные и пропускаемые выражения
Контекстные выражения — это выражения, которые допустимы только в определенных контекстах, например использование имен элементов в выражениях копирования и обновления без необходимости определять их.
Выражения можно опустить, если компилятор может вывести и автоматически вставить их, как это работает с операторами оценки и переназначения.
Есть еще один пример, применяемый к контекстным и опускаемым выражениям — диапазоны с неточными границами. Они допустимы только в определенном контексте, и компилятор преобразует их в обычные 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
). Обратное справедливо и для начала диапазона.
Говоря проще, если значение начала диапазона опущено, выведенное значение начала:
- будет равно нулю, если шаг не указан или если указанный шаг больше нуля;
- будет равно длине массива минус один, если указанный шаг меньше нуля.
Если значение окончания диапазона опущено, выведенное значение окончания:
- будет равно длине массива минус один, если шаг не указан или если указанный шаг больше нуля;
- будет равно нулю, если указанный шаг меньше нуля.
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
, если шаг не указан.