Precedencia y asociatividad
La precedencia y la asociatividad definen el orden en el que se aplican los operadores. Los operadores con mayor precedencia se enlazan primero a sus argumentos (operandos), mientras que los operadores con la misma precedencia se enlazan en la dirección de su asociatividad.
Por ejemplo, la expresión 1+2*3
según la precedencia para la suma y la multiplicación es equivalente a 1+(2*3)
, y 2^3^4
es igual a 2^(3^4)
ya que la exponenciación es asociativa a la derecha.
Operadores
La siguiente tabla enumera los operadores disponibles en Q#, así como su precedencia y asociatividad. También se enumeran los modificadores y combinadores adicionales, que se enlazan más estrechamente que cualquiera de estos operadores.
Descripción | Sintaxis | Operador | asociatividad | Prioridad |
---|---|---|---|---|
copy-and-update operator | w/ <- |
ternario | left | 1 |
operador range | .. |
infijo | left | 2 |
Operador condicional | ? \| |
ternario | right | 3 |
OR lógico | or |
infijo | left | 4 |
AND lógico | and |
infijo | left | 5 |
OR bit a bit | \|\|\| |
infijo | left | 6 |
XOR bit a bit | ^^^ |
infijo | left | 7 |
AND bit a bit | &&& |
infijo | left | 8 |
igualdad | == |
infijo | left | 9 |
desigualdad | != |
infijo | left | 9 |
menor que o igual que | <= |
infijo | left | 10 |
menor que | < |
infijo | left | 11 |
mayor o igual que | >= |
infijo | left | 11 |
mayor que | > |
infijo | left | 11 |
desplazamiento a la derecha | >>> |
infijo | left | 12 |
desplazamiento a la izquierda | <<< |
infijo | left | 12 |
suma o concatenación | + |
infijo | left | 13 |
resta | - |
infijo | left | 13 |
multiplicación | * |
infijo | left | 14 |
división | / |
infijo | left | 14 |
modulus | % |
infijo | left | 14 |
exponentiation | ^ |
infijo | right | 15 |
NOT bit a bit | ~~~ |
prefix | right | 16 |
operador NOT lógico | not |
prefix | right | 16 |
negative | - |
prefix | right | 16 |
Las expresiones Copy-and-update deben tener necesariamente la menor precedencia para garantizar un comportamiento coherente de la correspondiente instrucción evaluate-and-reassign. Consideraciones similares se aplican al operador de rango para garantizar un comportamiento coherente de la expresión contextual correspondiente.
Modificadores y combinaciones
Los modificadores se pueden considerar operadores especiales que solo se pueden aplicar a determinadas expresiones. Podemos asignarles una precedencia artificial para capturar su comportamiento.
Para más información, consulte Expresiones.
Esta precedencia artificial se enumera en la siguiente tabla, junto con la relación entre la precedencia de los operadores y los modificadores y el modo en que se vinculan los combinadores de acceso a elementos ([
,]
y ::
respectivamente) y los combinadores de invocación ((
,)
).
Descripción | Sintaxis | Operador | asociatividad | Prioridad |
---|---|---|---|---|
Combinador de llamada | ( ) |
N/D | left | 17 |
Functor Adjoint (adjunto) | Adjoint |
prefix | right | 18 |
Functor Controlled (controlado) | Controlled |
prefix | right | 18 |
Desajustar aplicación | ! |
postfix | left | 19 |
Acceso a elementos con nombre | :: |
N/D | left | 20 |
Acceso a los elementos de la matriz | [ ] |
N/D | left | 20 |
Función lambda | -> |
N/D | right | 21 |
Operación lambda | => |
N/D | right | 21 |
Para ilustrar las implicaciones de las precedencias asignadas, supongamos que tiene una operación unitaria DoNothing
(como la definida en Declaraciones de especialización), un invocable GetStatePrep
que devuelve una operación unitaria, y una matriz algorithms
que contiene elementos de tipo Algorithm
definida como
newtype Algorithm = (
Register : Qubit[],
Initialize : Transformation,
Apply : Transformation
);
newtype Transformation =
Qubit[] => Unit is Adj + Ctl;
Por tanto, todas las expresiones siguientes son válidas:
GetStatePrep()(arg)
(Transformation(GetStatePrep()))!(arg)
Adjoint DoNothing()
Controlled Adjoint DoNothing(cs, ())
Controlled algorithms[0]::Apply!(cs, _)
algorithms[0]::Register![i]
Si observamos las precedencias definidas en la tabla anterior, vemos que los paréntesis alrededor de(Transformation(GetStatePrep()))
son necesarios para que el operador unwrap posterior se aplique al valor de Transformation
y no a la operación devuelta.
Sin embargo, los paréntesis no son necesarios en GetStatePrep()(arg)
; las funciones se aplican de izquierda a derecha, por lo que esta expresión es equivalente a (GetStatePrep())(arg)
.
Las aplicaciones de functores tampoco requieren paréntesis a su alrededor para invocar la especialización correspondiente, y tampoco las matrices ni las expresiones de acceso a elementos. Por lo tanto, la expresión arr2D[i][j]
es perfectamente válida, como lo es algorithms[0]::Register![i]
.