Espressioni contestuali e omesse
Le espressioni contestuali sono espressioni valide solo in determinati contesti, ad esempio l'uso di nomi di elementi nelle espressioni di copia e aggiornamento senza doverli qualificare.
Le espressioni possono essere omesse quando possono essere dedotte e inserite automaticamente dal compilatore, ad esempio nel caso di istruzioni evaluate-and-reassign.
Gli intervalli aperti sono un altro esempio che si applicano alle espressioni contestuali e omesse. Sono validi solo all'interno di un determinato contesto e il compilatore li converte in espressioni normali Range
durante la compilazione dedurndo limiti appropriati.
Un valore di tipo Range
genera una sequenza di numeri interi, specificati da un valore iniziale, un valore di passaggio (facoltativo) e un valore finale. Ad esempio, l'espressione Range
1..3
letterale genera la sequenza 1,2,3. Analogamente, l'espressione 3..-1..1
genera la sequenza 3,2,1. È anche possibile usare gli intervalli per creare una nuova matrice da una esistente sezionando, ad esempio:
let arr = [1,2,3,4];
let slice1 = arr[1..2..4]; // contains [2,4]
let slice2 = arr[2..-1..0]; // contains [3,2,1]
Non è possibile definire un intervallo infinito in Q#. È sempre necessario specificare i valori iniziale e finale. L'unica eccezione è quando si usa un Range
oggetto per sezionare una matrice. In tal caso, i valori iniziale o finale dell'intervallo possono essere ragionevolmente dedotti dal compilatore.
Negli esempi di sezionamento della matrice precedente, è ragionevole che il compilatore presupporre che la fine dell'intervallo previsto sia l'indice dell'ultimo elemento nella matrice se la dimensione del passaggio è positiva. Se la dimensione del passaggio è negativa, la fine dell'intervallo dovrebbe essere probabilmente l'indice del primo elemento nella matrice, 0
. Il contrario tiene per l'inizio dell'intervallo.
Per riepilogare, se si omette il valore iniziale dell'intervallo, il valore iniziale dedotto
- è zero se non viene specificato alcun passaggio o il passaggio specificato è positivo.
- corrisponde alla lunghezza della matrice meno uno se l'incremento specificato è negativo.
Se si omette il valore finale dell'intervallo, il valore finale dedotto
- è la lunghezza della matrice meno uno se non viene specificato alcun passaggio o il passaggio specificato è positivo.
- è zero se l'incremento specificato è negativo.
Q# pertanto consente l'uso di intervalli aperti all'interno di espressioni di sezionamento di matrici, ad esempio:
let arr = [1,2,3,4,5,6];
let slice1 = arr[3...]; // slice1 is [4,5,6];
let slice2 = arr[0..2...]; // slice2 is [1,3,5];
let slice3 = arr[...2]; // slice3 is [1,2,3];
let slice4 = arr[...2..3]; // slice4 is [1,3];
let slice5 = arr[...2...]; // slice5 is [1,3,5];
let slice7 = arr[4..-2...]; // slice7 is [5,3,1];
let slice8 = arr[...-1..3]; // slice8 is [6,5,4];
let slice9 = arr[...-1...]; // slice9 is [6,5,4,3,2,1];
let slice10 = arr[...]; // slice10 is [1,2,3,4,5,6];
Poiché la determinazione del passaggio di intervallo è positivo o negativo in fase di esecuzione, il compilatore inserisce un'espressione appropriata che verrà valutata in fase di esecuzione. Per i valori finali omessi l'espressione inserita è step < 0 ? 0 | Length(arr)-1
, mentre per i valori iniziali omessi è step < 0 ? Length(arr)-1 | 0
, dove step
corrisponde all'espressione specificata per l'incremento dell'intervallo oppure 1
se non viene specificato alcun incremento.