Partage via


Priorité et associativité

Priorité et associativité définissent l’ordre dans lequel les opérateurs sont appliqués. Les opérateurs dotés d’une priorité plus élevée sont d’abord liés à leurs arguments (opérandes), tandis que les opérateurs dotés de la même priorité se lient dans la direction de leur associativité. Par exemple, l’expression 1+2*3 en fonction de la priorité pour l’addition et la multiplication est équivalente à 1+(2*3), et 2^3^4 à 2^(3^4) puisque l’élévation à une puissance est associative à droite.

Opérateurs

Le tableau suivant répertorie les opérateurs disponibles dans Q#, ainsi que leur priorité et leur associativité. Des modificateurs et combinateurs supplémentaires sont également répertoriés et se lient plus étroitement que tous ces opérateurs.

Description Syntaxe Opérateur Associativité Priorité
opérateur copy-and-update w/ <- ternaire gauche 1
Opérateur de plage .. Infixe gauche 2
opérateur conditionnel ? \| ternaire droite 3
OU logique or Infixe gauche 4
AND logique and Infixe gauche 5
OR au niveau du bit \|\|\| Infixe gauche 6
XOR au niveau du bit ^^^ Infixe gauche 7
AND au niveau du bit &&& Infixe gauche 8
égalité == Infixe gauche 9
inégalité != Infixe gauche 9
inférieur ou égal à <= Infixe gauche 10
inférieur à < Infixe gauche 11
supérieur ou égal à >= Infixe gauche 11
supérieur à > Infixe gauche 11
décalage vers la droite >>> Infixe gauche 12
décalage vers la gauche <<< Infixe gauche 12
addition ou concaténation + Infixe gauche 13
soustraction - Infixe gauche 13
multiplication * Infixe gauche 14
division / Infixe gauche 14
modulus % Infixe gauche 14
élévation à une puissance ^ Infixe droite 15
NOT au niveau du bit ~~~ prefix droite 16
NOT logique not prefix droite 16
negative - prefix droite 16

Les expressions copy-and-update doivent nécessairement avoir la priorité la plus faible pour garantir un comportement cohérent de l'instruction evaluate-and-reassigncorrespondante. Des considérations similaires s’appliquent à l’opérateur range pour garantir un comportement cohérent de l'expression contextuellecorrespondante.

Modificateurs et combinateurs

Les modificateurs peuvent être considérés comme des opérateurs spéciaux susceptibles d’être appliqués à certaines expressions uniquement. Il est possible de leur attribuer une priorité artificielle pour capturer leur comportement.

Pour plus d’informations, consultez Expressions.

Cette priorité artificielle est indiquée dans le tableau suivant, qui montre également comment la précédence des opérateurs et des modificateurs est liée à la façon dont les combinateurs d’accès aux éléments ([, ] et :: respectivement) et les combinateurs d’appel ((, )) se lient.

Description Syntaxe Opérateur Associativité Priorité
Combinateur d’appel ( ) n/a gauche 17
Foncteur adjoint Adjoint prefix droite 18
Foncteur contrôlé Controlled prefix droite 18
Application de l’opérateur unwrap ! postfix gauche 19
Accès aux éléments nommés :: n/a gauche 20
Accès aux éléments de tableau [ ] n/a gauche 20
Lambda de fonction -> n/a droite 21
Lambda d’opération => n/a droite 21

Pour illustrer les implications des précédences attribuées, supposons que nous ayons une opération unitaire DoNothing (telle que définie dans Déclarations de spécialisation), un callable GetStatePrep qui retourne une opération unitaire, et un tableau algorithms contenant des éléments de type Algorithm définis comme suit

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

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

Les expressions suivantes sont alors toutes valides :

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

En examinant les précédences définies dans le tableau ci-dessus, vous pouvez constater que les parenthèses entourant (Transformation(GetStatePrep())) sont nécessaires pour appliquer l’opérateur de désencapsulage à la valeur Transformation plutôt qu’à l’opération retournée. Cela étant, les parenthèses ne sont pas requises dans GetStatePrep()(arg). Les fonctions sont appliquées de gauche à droite et dès lors, cette expression est équivalente à (GetStatePrep())(arg). Les applications de foncteur n’ont pas non plus besoin de parenthèses pour appeler la spécialisation correspondante et il en va de même pour les expressions d’accès aux tableau et aux éléments nommés. Ainsi, l’expression arr2D[i][j] est parfaitement valide, tout comme algorithms[0]::Register![i].