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


Очередность и ассоциативность

Приоритет и ассоциативность определяют очередность применения операторов. Операторы с более высоким приоритетом привязываются к аргументам (операндам) в первую очередь, тогда как операторы с одинаковым приоритетом привязываются в направлении их ассоциативности. Например, выражение 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].