Compartir a través de


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