Accesso agli elementi

Q# supporta l'accesso agli elementi delle matrici e agli elementi nei tipi definiti dall'utente. In entrambi i casi, l'accesso è di sola lettura; Non è possibile modificare il valore senza creare una nuova istanza usando un'espressione di copia e aggiornamento.

Accesso a elementi di matrice e slicing di matrici

Data un'espressione di matrice e un'espressione di tipo Int o Range, è possibile creare una nuova espressione usando l'operatore di accesso agli elementi delle matrici costituito da [ e ].

Se l'espressione all'interno delle parentesi quadre è di tipo Int, la nuova espressione contiene l'elemento della matrice in corrispondenza di tale indice. Ad esempio, se arr è di tipo Double[] e contiene cinque o più elementi, arr[4] è un'espressione di tipo Double.

Se l'espressione all'interno delle parentesi quadre è di tipo Range, la nuova espressione contiene una matrice di tutti gli elementi indicizzati dall'oggetto specificato Range. Se è Range vuoto, la matrice risultante è vuota. Ad esempio,

let arr = [10, 11, 36, 49];
let ten = arr[0]; // contains the value 10
let odds = arr[1..2..4]; // contains the value [11, 49]
let reverse = arr[...-1...]; // contains the value [49, 36, 11, 10]

Nell'ultima riga dell'esempio il valore iniziale e finale dell'intervallo è stato omesso per praticità. Per altre informazioni, vedere Espressioni contestuali.

Se l'espressione di matrice non è un identificatore semplice, deve essere racchiusa tra parentesi per estrarre un elemento o una sezione. Ad esempio, se arr1 e arr2 sono entrambe matrici di interi, un elemento dalla concatenazione verrebbe espresso come (arr1 + arr2)[13]. Per altre informazioni, vedere Precedenza e associatività.

Tutte le matrici in Q# sono in base zero, ovvero il primo elemento di una matrice arr è sempre arr[0]. In fase di esecuzione viene generata un'eccezione se l'indice o uno degli indici utilizzati per il sezionamento non rientra nei limiti della matrice, ad esempio se è minore di zero o maggiore o uguale alla lunghezza della matrice.

Accesso agli elementi per i tipi definiti dall'utente

Per altre informazioni su come definire tipi personalizzati contenenti uno o più elementi denominati o anonimi, vedere Dichiarazioni di tipo.

È possibile accedere agli elementi contenuti tramite il nome o la decostruzione, illustrati dalle istruzioni seguenti che possono essere usate come parte di un'implementazione di un'operazione o di una funzione:

    let complex = Complex(1., 0.); // create a value of type Complex
    let (re, _) = complex!;       // item access via deconstruction
    let im = complex::Imaginary;  // item access via name

L'operatore di accesso agli elementi (::) recupera gli elementi denominati, come illustrato nell'esempio seguente:

newtype TwoStrings = (str1 : String, str2 : String);

operation LinkTwoStrings(str : TwoStrings) : String {
    let s1 = str::str1;
    let s2 = str::str2;
    return s1 + s2;
}

Mentre gli elementi denominati sono accessibili tramite il nome o tramite decostruzione, gli elementi anonimi sono accessibili solo tramite quest'ultima tecnica. Poiché la decostruzione si basa su tutti gli elementi contenuti, l'uso di elementi anonimi è sconsigliato quando questi elementi devono essere accessibili all'esterno dell'unità di compilazione in cui è definito il tipo.

L'accesso tramite decostruzione usa l'operatore unwrap (!). L'operatore unwrap restituisce una tupla di tutti gli elementi contenuti, in cui la forma della tupla corrisponde a quella definita nella dichiarazione e una tupla di un singolo elemento equivale all'elemento stesso (vedere questa sezione).

Ad esempio, per un valore nested di tipo Nested definito come segue

newtype Nested = (Double, (ItemName : Int, String));

l'espressione nested! restituisce un valore di tipo (Double, (Int, String)).

L'operatore ! ha una precedenza inferiore rispetto a entrambi gli operatori di accesso agli elementi, ma ha una precedenza maggiore rispetto a qualsiasi altro operatore. Per un elenco completo delle precedenze, vedere Precedenza e associatività.