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 sono associati 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 associano più strettamente rispetto a uno di questi operatori.

Descrizione Sintassi Operatore Associatività Precedenza
operatori di copia e aggiornamento w/ <- ternario sinistro 1
Operatore range .. infisso sinistro 2
operatore condizionale ? \| ternario right 3
OR logico or infisso sinistro 4
AND logico and infisso sinistro 5
OR bit per bit \|\|\| infisso sinistro 6
XOR bit per bit ^^^ infisso sinistro 7
AND bit per bit &&& infisso sinistro 8
uguaglianza == infisso sinistro 9
disuguaglianza != infisso sinistro 9
minore o uguale a <= infisso sinistro 10
minore di < infisso sinistro 11
maggiore o uguale a >= infisso sinistro 11
maggiore di > infisso sinistro 11
spostamento a destra >>> infisso sinistro 12
spostamento a sinistra <<< infisso sinistro 12
addizione o concatenazione + infisso sinistro 13
sottrazione - infisso sinistro 13
moltiplicazione * infisso sinistro 14
divisione / infisso sinistro 14
modulo % infisso sinistro 14
elevamento a potenza ^ infisso right 15
NOT bit per bit ~~~ prefix right 16
NOT logico not prefix right 16
negativo - 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 ((, )) si associano.

Descrizione Sintassi Operatore Associatività Precedenza
Combinatore di chiamata ( ) n/d sinistro 17
Funtore Adjoint Adjoint prefix right 18
Funtore Controlled Controlled prefix right 18
Applicazione di unwrap ! postfix sinistro 19
Accesso agli elementi denominati :: n/d sinistro 20
Accesso agli elementi della matrice [ ] n/d sinistro 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 unitaria (come definito nelle dichiarazioni di specializzazione), un 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 sono (Transformation(GetStatePrep())) 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 intorno a esse per richiamare la specializzazione corrispondente, né le espressioni di accesso alla matrice o all'elemento denominato. Pertanto, l'espressione arr2D[i][j] è perfettamente valida, così come è algorithms[0]::Register![i].