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