Condividi tramite


Dichiarazioni di variabili e riassegnazioni

I valori possono essere associati ai simboli usando le istruzioni let e mutable. Questi tipi di associazioni offrono un modo pratico per accedere a un valore tramite l'handle definito. Nonostante la terminologia fuorviante presa in prestito da altri linguaggi, gli handle dichiarati in un ambito locale e i valori contenenti vengono chiamati variabili . Questo può essere fuorviante perché let istruzioni definiscono handle a assegnazione singola, che sono handle che rimangono associati allo stesso valore per la durata della validità. Le variabili che possono essere ri-associate a valori diversi in punti diversi nel codice devono essere dichiarate in modo esplicito come tali e vengono specificate usando l'istruzione mutable.

    let var1 = 3; 
    mutable var2 = 3; 
    var2 = var2 + 1; 

In questo esempio, l'istruzione let dichiara una variabile denominata var1 che non può essere riassegnata e contiene sempre il valore 3. L'istruzione mutable definisce una variabile var2 associata temporaneamente al valore 3, ma può essere riassegnata a un valore diverso in un secondo momento usando un'espressione di assegnazione, come illustrato nell'ultima riga. È possibile esprimere la stessa istruzione con la versione più breve var2 += 1;, come è comune in altri linguaggi. Per altre informazioni, vedere evaluate and reassign statements.

Per riepilogare:

  • let viene usato per creare un'associazione non modificabile.
  • mutable viene usato per creare un'associazione modificabile.
  • = senza un let viene usato per modificare il valore di un'associazione modificabile.

Per tutte e tre le istruzioni, il lato sinistro è costituito da un simbolo o da una tupla di simboli. Se il lato destro dell'associazione è una tupla, tale tupla può essere completamente o parzialmente decostruita all'assegnazione. L'unico requisito per la decostruzione è che la forma della tupla sul lato destro corrisponde alla forma della tupla simbolo sul lato sinistro. La tupla dei simboli può contenere tuple annidate o simboli omessi o entrambi, indicati da un carattere di sottolineatura. Per esempio:

let (a, (_, b)) = (1, (2, 3)); // a is bound to 1, b is bound to 3
mutable (x, y) = ((1, 2), [3, 4]); // x is bound to (1, 2), y is bound to [3, 4]
(x, _, y) = ((5, 6), 7, [8]);  // x is re-bound to (5,6), y is re-bound to [8]

Per altre informazioni sulla decostruzione tramite l'operatore unwrap (!) , vedere accesso all'elemento per i tipi di struct.

Tutte le assegnazioni in Q# rispettano le stesse regole di decostruzione, tra cui, ad esempio, allocazioni di qubit e assegnazioni di variabili di ciclo.

Per entrambi i tipi di associazioni, i tipi delle variabili vengono dedotti dal lato destro dell'associazione. Il tipo di una variabile rimane sempre lo stesso e un'espressione di assegnazione non può modificarla. Le variabili locali possono essere dichiarate come modificabili o non modificabili. Esistono alcune eccezioni, ad esempio le variabili di ciclo nei cicli for, in cui il comportamento è predefinito e non può essere specificato. Gli argomenti della funzione e dell'operazione sono sempre associati in modo non modificabile. In combinazione con la mancanza di tipi riferimento, come illustrato nell'argomento immutabilità, ciò significa che una funzione o un'operazione chiamata non può mai modificare alcun valore sul lato chiamante.

Poiché gli stati di Qubit valori non sono definiti o osservabili dall'interno di Q#, questo non impedisce l'accumulo di effetti collaterali quantistici, che sono osservabili solo tramite le misurazioni. Per altre informazioni, vedere tipi di dati Quantum.

Indipendentemente dalla modalità di associazione di un valore, i valori stessi non sono modificabili. In particolare, questo vale per le matrici e gli elementi di matrice. A differenza dei linguaggi classici più diffusi in cui le matrici sono spesso tipi di riferimento, matrici in Q#, come tutti i tipi, sono tipi di valore e sempre non modificabili; ovvero, non è possibile modificarli dopo l'inizializzazione. La modifica dei valori a cui si accede dalle variabili di tipo matrice richiede quindi la costruzione esplicita di una nuova matrice e la riassegnazione allo stesso simbolo. Per altre informazioni, vedere di immutabilità e copiare e aggiornare le espressioni.

Istruzioni Evaluate-and-reassign

Le istruzioni del modulo intValue += 1; sono comuni in molti altri linguaggi. In questo caso, intValue deve essere una variabile associato mutably di tipo Int. Tali istruzioni forniscono un modo pratico di concatenazione se il lato destro consiste nell'applicare un operatore binario e il risultato viene rebound all'argomento sinistro dell'operatore. Ad esempio, questo segmento di codice

mutable counter = 0;
for i in 1 .. 2 .. 10 {
    counter += 1;
    // ...
}

incrementa il valore del contatore counter in ogni iterazione del ciclo for ed è equivalente a

mutable counter = 0;
for i in 1 .. 2 .. 10 {
    counter = counter + 1;
    // ...
}

Esistono istruzioni simili per un'ampia gamma di operatori . Tali espressioni evaluate-and-reassign esistono per tutti gli operatori in cui il tipo di espressione secondaria più a sinistra corrisponde al tipo di espressione. Più precisamente, sono disponibili per operatori logici e bit per bit binari, inclusi spostamento a destra e sinistra, espressioni aritmetiche, tra cui exponentiation e moduli e concatenazioni, nonché espressioni di copia e aggiornamento.

Nell'esempio di funzione seguente viene calcolata la somma di una matrice di numeri Complex:

function ComplexSum(values : Complex[]) : Complex {
    mutable res = Complex(0., 0.);
    for complex in values {
        res = new Complex { Re = res.Re + complex.Re, Im = res.Im + complex.Im };
    }
    return res;
}

Analogamente, la funzione seguente moltiplica ogni elemento in una matrice con il fattore specificato:

function Multiplied(factor : Double, array : Double[]) : Double[] {
    mutable res = new Double[Length(array)];
    for i in IndexRange(res) {
        res w/= i <- factor * array[i];
    }
    return res;
}

Per altre informazioni, vedere espressioni contestuali, che contiene altri esempi in cui le espressioni possono essere omesse in un contesto specifico quando è possibile dedurre un'espressione appropriata dal compilatore.