Condividi tramite


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