Поделиться через


Доступ к элементам

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)).

Оператор ! имеет более низкий приоритет, чем оба оператора доступа к элементам, но более высокий приоритет, чем любой другой оператор. Полный список приоритетов см. в разделе Очередность и ассоциативность.