Precedenza e associatività
La precedenza e l'associatività definiscono l'ordine in cui vengono applicati gli operatori. Gli operatori con precedenza più alta sono associati prima ai relativi argomenti (operandi), mentre gli operatori con la stessa precedenza si associano nella direzione della loro associatività.
Ad esempio, in base all'ordine di precedenza per addizione e moltiplicazione l'espressione 1+2*3
equivale a 1+(2*3)
e 2^3^4
è uguale a 2^(3^4)
dal momento che l'elevamento a potenza è associativo a destra.
Operatori
Nella tabella seguente sono elencati gli operatori disponibili in Q#, nonché la precedenza e l'associatività. Sono elencati anche modificatori e combinatori aggiuntivi e si associano più strettamente di uno di questi operatori.
Descrizione | Sintassi | Operatore | Associatività | Precedenza |
---|---|---|---|---|
operatori di copia e aggiornamento | w/ <- |
ternario | left | 1 |
Operatore range | .. |
infisso | left | 2 |
operatore condizionale | ? \| |
ternario | right | 3 |
OR logico | or |
infisso | left | 4 |
AND logico | and |
infisso | left | 5 |
OR bit per bit | \|\|\| |
infisso | left | 6 |
XOR bit per bit | ^^^ |
infisso | left | 7 |
AND bit per bit | &&& |
infisso | left | 8 |
uguaglianza | == |
infisso | left | 9 |
disuguaglianza | != |
infisso | left | 9 |
minore o uguale a | <= |
infisso | left | 10 |
minore di | < |
infisso | left | 11 |
maggiore o uguale a | >= |
infisso | left | 11 |
maggiore di | > |
infisso | left | 11 |
spostamento a destra | >>> |
infisso | left | 12 |
spostamento a sinistra | <<< |
infisso | left | 12 |
addizione o concatenazione | + |
infisso | left | 13 |
sottrazione | - |
infisso | left | 13 |
moltiplicazione | * |
infisso | left | 14 |
divisione | / |
infisso | left | 14 |
modulo | % |
infisso | left | 14 |
elevamento a potenza | ^ |
infisso | right | 15 |
NOT bit per bit | ~~~ |
prefix | right | 16 |
NOT logico | not |
prefix | right | 16 |
negative | - |
prefix | right | 16 |
Le espressioni di copia e aggiornamento devono necessariamente avere minore precedenza per garantire un comportamento coerente dell'istruzione di valutazione e riassegnazione corrispondente. Considerazioni simili valgono per l'operatore di intervallo per garantire un comportamento coerente dell'espressione contestuale corrispondente.
Modificatori e combinatori
I modificatori possono essere considerati operatori speciali che possono essere applicati solo a determinate espressioni. È possibile assegnare una precedenza artificiale per acquisire il proprio comportamento.
Per altre informazioni, vedere Espressioni.
Questa precedenza artificiale è elencata nella tabella seguente, insieme al modo in cui la precedenza degli operatori e dei modificatori è correlata al modo in cui i combinatori di accesso agli elementi ([
]
e rispettivamente) e ::
i combinatori di chiamata ((
, )
) associano.
Descrizione | Sintassi | Operatore | Associatività | Precedenza |
---|---|---|---|---|
Combinatore di chiamata | ( ) |
n/d | left | 17 |
Funtore Adjoint | Adjoint |
prefix | right | 18 |
Funtore Controlled | Controlled |
prefix | right | 18 |
Applicazione di unwrap | ! |
postfix | left | 19 |
Accesso agli elementi denominati | :: |
n/d | left | 20 |
Accesso agli elementi della matrice | [ ] |
n/d | left | 20 |
Funzione lambda | -> |
n/d | right | 21 |
Espressione lambda dell'operazione | => |
n/d | right | 21 |
Per illustrare le implicazioni delle precedenze assegnate, si supponga di avere un'operazione DoNothing
unità (come definito nelle dichiarazioni di specializzazione), un'operazione chiamabile GetStatePrep
che restituisce un'operazione unitaria e una matrice algorithms
che contiene elementi di tipo Algorithm
definiti come segue
newtype Algorithm = (
Register : Qubit[],
Initialize : Transformation,
Apply : Transformation
);
newtype Transformation =
Qubit[] => Unit is Adj + Ctl;
Le espressioni seguenti, quindi, sono tutte valide:
GetStatePrep()(arg)
(Transformation(GetStatePrep()))!(arg)
Adjoint DoNothing()
Controlled Adjoint DoNothing(cs, ())
Controlled algorithms[0]::Apply!(cs, _)
algorithms[0]::Register![i]
Esaminando le precedenze definite nella tabella precedente, è possibile notare che le parentesi (Transformation(GetStatePrep()))
sono necessarie affinché l'operatore di annullamento del wrapping successivo venga applicato al valore anziché all'operazione Transformation
restituita.
Le parentesi non sono tuttavia obbligatorie in GetStatePrep()(arg)
. Le funzioni vengono applicate da sinistra a destra, quindi questa espressione equivale a (GetStatePrep())(arg)
.
Le applicazioni functor non richiedono anche parentesi per richiamare la specializzazione corrispondente, né le espressioni di accesso a matrici o elementi denominati. Pertanto, l'espressione arr2D[i][j]
è perfettamente valida, come è algorithms[0]::Register![i]
.