Доступ к элементам
Q# поддерживает доступ к элементам массивов и пользовательских типов. В обоих случаях доступ предоставляется только для чтения, т. е. значение изменить невозможно; можно лишь создать новый экземпляр с помощью выражения копирования и обновления.
Доступ к элементам массива и создание срезов массивов
При наличии выражения массива и выражения типа Int
или Range
можно сформировать новое выражение с помощью оператора доступа к элементам массива, состоящего из квадратных скобок [
и ]
.
Если выражение в квадратных скобках относится к типу Int
, новое выражение будет содержать элемент массива по этому индексу.
Например, если массив arr
имеет тип Double[]
и содержит пять или более элементов, arr[4]
является выражением типа Double
.
Если выражение в квадратных скобках имеет тип Range
, новое выражение будет содержать массив всех элементов с индексами по указанному Range
. Если диапазон Range
пуст, итоговый массив будет пустым.
Например, примененная к объекту директива
let arr = [10, 11, 36, 49];
let ten = arr[0]; // contains the value 10
let odds = arr[1..2..4]; // contains the value [11, 49]
let reverse = arr[...-1...]; // contains the value [49, 36, 11, 10]
В последней строке примера начальное и конечное значения диапазона опущены для удобства. Дополнительные сведения см. в разделе Контекстные и пропускаемые выражения.
Если выражение массива не является простым идентификатором, оно должно быть заключено в круглые скобки для извлечения элемента или среза.
Например, если arr1
и arr2
являются массивами целых чисел, то элемент из их объединения будет выражен в виде (arr1 + arr2)[13]
. Дополнительные сведения см. в разделе Очередность и ассоциативность.
Все массивы в Q# основаны на нулях, то есть первый элемент массива arr
всегда имеет значение arr[0]
.
Если отдельный индекс или один из индексов, используемых для среза, выходит за пределы границ массива, то есть меньше нуля либо больше или равен длине массива, создается исключение.
Доступ к элементам пользовательских типов
(Дополнительные сведения о том, как определить пользовательские типы, содержащие один или несколько именованных или анонимных элементов, см. в разделе Объявления типов).
Доступ к содержащимся элементам можно получить через их имя или деконструкцию, проиллюстрированные следующими инструкциями, которые могут использоваться в рамках реализации операции или функции:
let complex = Complex(1., 0.); // create a value of type Complex
let (re, _) = complex!; // item access via deconstruction
let im = complex::Imaginary; // item access via name
Оператор доступа к элементам (::
) извлекает именованные элементы, как показано в следующем примере:
newtype TwoStrings = (str1 : String, str2 : String);
operation LinkTwoStrings(str : TwoStrings) : String {
let s1 = str::str1;
let s2 = str::str2;
return s1 + s2;
}
В то время как к именованным элементам можно обращаться по имени или путем деконструирования, доступ к анонимным элементам возможен только вторым способом. Так как деконструкция зависит от всех содержащихся элементов, использование анонимных элементов не рекомендуется, если к этим элементам требуется доступ за пределами единицы компиляции, в которой определен тип.
Для доступа посредством деконструирования используется оператор распаковки (!
). Он возвращает кортеж всех элементов типа, причем форма кортежа совпадает с определенной в объявлении, а одноэлементный кортеж эквивалентен самому элементу (см. этот раздел).
Например, для значения nested
типа Nested
, это определено следующим образом:
newtype Nested = (Double, (ItemName : Int, String));
выражение nested!
возвращает значение типа (Double, (Int, String))
.
Оператор !
имеет более низкий приоритет, чем оба оператора доступа к элементам, но более высокий приоритет, чем любой другой оператор. Полный список приоритетов см. в разделе Очередность и ассоциативность.