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