Очередность и ассоциативность
Приоритет и ассоциативность определяют очередность применения операторов. Операторы с более высоким приоритетом привязываются к аргументам (операндам) в первую очередь, тогда как операторы с одинаковым приоритетом привязываются в направлении их ассоциативности.
Например, выражение 1+2*3
согласно приоритету сложения и умножения эквивалентно выражению 1+(2*3)
, а 2^3^4
эквивалентно 2^(3^4)
, так как возведение в степень является правоассоциативным.
Операторы
В таблице ниже приведены доступные операторы в Q# с указанием их приоритета и ассоциативности. Также приведены дополнительные модификаторы и комбинаторы, которые обеспечивают более тесную привязку, чем любые операторы.
Description | Синтаксис | Оператор | Ассоциативность | Приоритет |
---|---|---|---|---|
оператор копирования и обновления | w/ <- |
троичный | left | 1 |
Оператор range | .. |
инфикс | left | 2 |
условный оператор | ? \| |
троичный | right | 3 |
логическое ИЛИ | or |
инфикс | left | 4 |
логическое И | and |
инфикс | left | 5 |
побитовое ИЛИ | \|\|\| |
инфикс | left | 6 |
побитовое исключающее ИЛИ | ^^^ |
инфикс | left | 7 |
побитовое И | &&& |
инфикс | left | 8 |
равенство | == |
инфикс | left | 9 |
неравенство | != |
инфикс | left | 9 |
меньше или равно | <= |
инфикс | left | 10 |
меньше | < |
инфикс | left | 11 |
больше или равно | >= |
инфикс | left | 11 |
больше | > |
инфикс | left | 11 |
сдвиг вправо | >>> |
инфикс | left | 12 |
сдвиг влево | <<< |
инфикс | left | 12 |
сложение или объединение | + |
инфикс | left | 13 |
вычитание | - |
инфикс | left | 13 |
умножение | * |
инфикс | left | 14 |
деление | / |
инфикс | left | 14 |
остаток от деления | % |
инфикс | left | 14 |
возведение в степень | ^ |
инфикс | right | 15 |
побитовое НЕ | ~~~ |
prefix | right | 16 |
логическое НЕ | not |
prefix | right | 16 |
negative | - |
prefix | right | 16 |
Выражения копирования и обновления должны иметь самый низкий приоритет, чтобы обеспечить согласованное поведение соответствующего оператора вычисления и переприсваивания. То же самое верно в отношении оператора диапазона, так как должно обеспечиваться единообразное поведение соответствующего контекстного выражения.
Модификаторы и методы объединения
Модификаторы можно рассматривать как специальные операторы, применимые только к определенным выражениям. Они позволяют принудительно изменять очередность выполнения операторов.
Дополнительные сведения см. в разделе Выражения.
В таблице ниже представлен принудительный приоритет, а также определено влияние приоритета операторов и модификаторов на степень привязки комбинаторов доступа ([
,]
и ::
соответственно) с комбинаторами вызова ((
, )
).
Description | Синтаксис | Оператор | Ассоциативность | Приоритет |
---|---|---|---|---|
Комбинатор вызова | ( ) |
Н/Д | left | 17 |
Функтор Adjoint | Adjoint |
prefix | right | 18 |
Функтор Controlled | Controlled |
prefix | right | 18 |
Оператор распаковки | ! |
postfix | left | 19 |
Доступ к именованным элементам | :: |
Н/Д | left | 20 |
Доступ к элементам массива | [ ] |
Н/Д | left | 20 |
Лямбда-функция | -> |
Н/Д | right | 21 |
Лямбда-операция | => |
Н/Д | right | 21 |
Чтобы показать, как работает назначенный приоритет, предположим, что имеется унитарная операция DoNothing
(определенная в разделе Объявления специализаций), вызываемый объект GetStatePrep
, возвращающий унитарную операцию, и массив algorithms
, содержащий элементы типа Algorithm
, которые определены следующим образом:
newtype Algorithm = (
Register : Qubit[],
Initialize : Transformation,
Apply : Transformation
);
newtype Transformation =
Qubit[] => Unit is Adj + Ctl;
В этом случае допустимы следующие выражения:
GetStatePrep()(arg)
(Transformation(GetStatePrep()))!(arg)
Adjoint DoNothing()
Controlled Adjoint DoNothing(cs, ())
Controlled algorithms[0]::Apply!(cs, _)
algorithms[0]::Register![i]
Согласно приоритетам, указанным в таблице выше, мы видим, что круглые скобки вокруг (Transformation(GetStatePrep()))
необходимы для применения последующего оператора распаковки к значению Transformation
, а не к возвращаемой операции.
Однако в GetStatePrep()(arg)
круглые скобки не требуются: функции применяются слева направо, поэтому это выражение эквивалентно (GetStatePrep())(arg)
.
При применении функторов их также не требуется заключать в круглые скобки для вызова соответствующей специализации. Это справедливо и для выражений доступа к массивам или именованным элементам. Поэтому выражение arr2D[i][j]
является совершенно допустимым, как и algorithms[0]::Register![i]
.