Partilhar via


Precedência e associatividade

Precedência e associatividade definem a ordem em que os operadores são aplicados. Os operadores com maior precedência são vinculados aos seus argumentos (operandos) primeiro, enquanto os operadores com a mesma precedência se ligam na direção de sua associatividade. Por exemplo, a expressão 1+2*3 de acordo com a precedência para adição e multiplicação é equivalente a 1+(2*3), e 2^3^4 é igual, uma vez que a 2^(3^4) exponenciação é associativa à direita.

Operadores

A tabela a seguir lista os operadores disponíveis no Q#, bem como sua precedência e associatividade. Modificadores e combinadores adicionais também são listados e ligam mais do que qualquer um desses operadores.

Description Sintaxe Operador Associatividade Precedência
Operador de cópia e atualização w/ <- ternário left 1
Operador de Gama .. Infix left 2
operador condicional ? \| ternário Certo 3
lógico OU or Infix left 4
lógica E and Infix left 5
bit a bit OU \|\|\| Infix left 6
XOR bit a bit ^^^ Infix left 7
bit a bit E &&& Infix left 8
igualdade == Infix left 9
desigualdade != Infix left 9
menos do que ou igual <= Infix left 10
menos do que < Infix left 11
maior que ou igual >= Infix left 11
maior do que > Infix left 11
Deslocamento para a direita >>> Infix left 12
Desvio para a esquerda <<< Infix left 12
adição ou concatenação + Infix left 13
Subtração - Infix left 13
multiplicação * Infix left 14
Divisão / Infix left 14
módulo % Infix left 14
exponenciação ^ Infix Certo 15
bit a bit NÃO ~~~ prefixo Certo 16
lógico NÃO not prefixo Certo 16
Negativo - prefixo Certo 16

As expressões de copiar e atualizar precisam necessariamente ter a menor precedência para garantir um comportamento consistente da instrução de avaliação e reatribuição correspondente. Considerações semelhantes valem para o operador de intervalo para garantir um comportamento consistente da expressão contextual correspondente.

Modificadores e combinadores

Os modificadores podem ser vistos como operadores especiais que podem ser aplicados apenas a determinadas expressões. Pode-lhes ser atribuída uma precedência artificial para capturar o seu comportamento.

Para obter mais informações, consulte Expressões.

Essa precedência artificial é listada na tabela a seguir, juntamente com a forma como a precedência dos operadores e modificadores se relaciona com a estreita ligação dos combinadores de acesso ao item ([,] e :: respectivamente) e dos combinadores de chamada ((, )).

Description Sintaxe Operador Associatividade Precedência
Combinador de chamadas ( ) n/d left 17
Functor adjunto Adjoint prefixo Certo 18
Functor controlado Controlled prefixo Certo 18
Desembrulhar aplicação ! Postfix left 19
Acesso ao item nomeado :: n/d left 20
Acesso a itens de matriz [ ] n/d left 20
Função lambda -> n/d Certo 21
Operação lambda => n/d Certo 21

Para ilustrar as implicações das precedências atribuídas, suponha que você tenha uma operação DoNothing unitária (conforme definido em Declarações de especialização), um chamável GetStatePrep que retorna uma operação unitária e uma matriz algorithms que contém itens do tipo Algorithm definido da seguinte forma

    newtype Algorithm = (
        Register : Qubit[],
        Initialize : Transformation,
        Apply : Transformation
    );

    newtype Transformation =
        Qubit[] => Unit is Adj + Ctl;

As seguintes expressões, então, são todas válidas:

    GetStatePrep()(arg)
    (Transformation(GetStatePrep()))!(arg)
    Adjoint DoNothing()
    Controlled Adjoint DoNothing(cs, ())
    Controlled algorithms[0]::Apply!(cs, _)
    algorithms[0]::Register![i]

Observando as precedências definidas na tabela acima, você pode ver que os parênteses ao redor (Transformation(GetStatePrep())) são necessários para que o operador de desempacotamento subsequente seja aplicado ao Transformation valor em vez da operação retornada. No entanto, parênteses não são necessários em GetStatePrep()(arg)funções são aplicadas da esquerda para a direita, de modo que esta expressão é equivalente a (GetStatePrep())(arg). Os aplicativos functor também não exigem parênteses em torno deles para invocar a especialização correspondente, nem expressões de acesso a array ou item nomeado. Assim, a expressão arr2D[i][j] é perfeitamente válida, assim como algorithms[0]::Register![i].