Freigeben über


Variablendeklarationen und Neuzuweisungen

Werte können über die Anweisungen let und mutable an Symbole gebunden werden. Derartige Bindungen bieten eine bequeme Möglichkeit, über das definierte Handle auf einen Wert zu zugreifen. Trotz der irreführenden Terminologie, die aus anderen Sprachen entlehnt wurde, werden Handles, die für einen lokalen Bereich deklariert sind und Werte enthalten, Variablen genannt. Das kann irreführend sein, da let-Anweisungen Einzelzuweisungshandles definieren. Das sind Handles, die für die Dauer ihrer Gültigkeit an den gleichen Wert gebunden bleiben. Variablen, die an verschiedenen Punkten im Code neu an unterschiedliche Werte gebunden werden können, müssen explizit als solche deklariert werden. Hierzu wird die mutable-Anweisung verwendet.

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

In diesem Beispiel deklariert die let-Anweisung eine Variable mit dem Namen var1, die nicht neu zugewiesen werden kann und immer den Wert 3 enthält. Die mutable-Anweisung definiert eine Variable (var2), die vorübergehend an den Wert 3 gebunden wird, aber später mithilfe einer set-Anweisung einem anderen Wert zugewiesen werden kann, wie in der letzten Zeile zu sehen. Sie können die gleiche Anweisung mit der kürzeren Version set var2 += 1; ausdrücken, wie in anderen Sprachen üblich. Weitere Informationen finden Sie unter Anweisungen zur Auswertung und Neuzuweisung.

Zusammenfassung:

  • let wird verwendet, um eine unveränderliche Bindung zu erstellen.
  • mutable wird verwendet, um eine veränderliche Bindung zu erstellen.
  • set wird verwendet, um den Wert einer veränderlichen Bindung zu ändern.

Bei allen drei Anweisungen besteht die linke Seite aus einem Symbol oder einem Symboltupel. Wenn die rechte Seite der Bindung ein Tupel ist, kann dieses Tupel bei der Zuweisung vollständig oder teilweise dekonstruiert werden. Die einzige Voraussetzung für die Dekonstruktion ist, dass die Form des Tupels auf der rechten Seite mit der Form des Symboltupels auf der linken Seite übereinstimmt. Das Symboltupel kann geschachtelte Tupel und/oder ausgelassene Symbole enthalten, die durch einen Unterstrich gekennzeichnet sind. Beispiel:

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]
set (x, _, y) = ((5, 6), 7, [8]);  // x is re-bound to (5,6), y is re-bound to [8]

Für alle Zuweisungen in Q# gelten die gleichen Dekonstruktionsregeln – einschließlich Qubitzuordnungen und Schleifenvariablenzuweisungen.

Für beide Arten von Bindungen werden die Typen der Variablen von der rechten Seite der Bindung abgeleitet. Der Typ einer Variablen bleibt immer gleich und kann nicht durch eine set-Anweisung geändert werden. Lokale Variablen können entweder als veränderlich oder als unveränderlich deklariert werden. Es gibt einige Ausnahmen wie etwa Schleifenvariablen in for-Schleifen, für die das Verhalten vordefiniert ist und nicht angegeben werden kann. Funktions- und Vorgangsargumente sind immer unveränderlich gebunden. In Kombination mit dem Fehlen von Verweistypen, wie im Thema Unveränderlichkeit erläutert, bedeutet dies, dass eine aufgerufene Funktion oder ein aufgerufener Vorgang niemals Werte auf der aufrufenden Seite ändern kann.

Da die Zustände von Qubit-Werten nicht innerhalb von Q# definiert oder beobachtbar sind, schließt dies nicht die Ansammlung von Quantennebeneffekten aus, die nur über Messungen beobachtbar sind. Weitere Informationen finden Sie unter Quantum-Datentypen.

Unabhängig von der Bindung eines Werts sind die Werte selbst unveränderlich. Das gilt insbesondere für Arrays und Arrayelemente. Anders als bei gängigen klassischen Sprachen, in denen Arrays häufig Verweistypen sind, handelt es sich bei Arrays in Q# wie bei allen Typen um Werttypen, die immer unveränderlich sind. Das bedeutet, sie können nach der Initialisierung nicht mehr geändert werden. Zum Ändern der Werte, auf die von Variablen des Arraytyps zugegriffen wird, muss explizit ein neues Array erstellt und dem gleichen Symbol neu zugewiesen werden. Weitere Informationen finden Sie in den Abschnitten Unveränderlichkeit und Copy-and-Update-Ausdrücke.

Anweisungen zur Auswertung und Neuzuweisung

Anweisungen in der Form set intValue += 1; sind in vielen anderen Sprachen üblich. Hier muss intValue eine veränderlich gebundene Variable vom Typ Int sein. Solche Anweisungen bieten eine praktische Möglichkeit der Verkettung, wenn die rechte Seite aus der Anwendung eines binären Operators besteht und das Ergebnis wieder an das linke Argument des Operators gebunden wird. Beispiel:

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

Das obige Codesegment erhöht den Wert des Zählers counter in jeder Iteration der for-Schleife und entspricht Folgendem:

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

Ähnliche Anweisungen sind für eine Vielzahl von Operatoren vorhanden. Auf das Schlüsselwort set muss in solchen Anweisungen zur Auswertung und Neuzuweisung eine einzelne veränderliche Variable folgen, die vom Compiler am äußerst linken Rand als Unterausdruck eingefügt wird. Solche Bewertungs-und-Neuzuweisungs-Anweisungen sind für alle Operatoren vorhanden, bei denen der Typ des äußerst linken Unterausdrucks dem Ausdruckstyp entspricht. Genauer gesagt sind sie für binäre logische und bitweise Operatoren (einschließlich Verschiebung nach rechts und links), für arithmetische Ausdrücke (einschließlich Potenzierung und Modulus) und für Verkettungen sowie für Copy-and-Update-Ausdrücke verfügbar.

Im folgenden Funktionsbeispiel wird beispielsweise die Summe eines Complex-Zahlenarrays berechnet:

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

In ähnlicher Weise multipliziert die folgende Funktion jedes Element in einem Array mit dem angegebenen Faktor:

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

Weitere Informationen finden Sie unter Kontextbezogene und ausgelassene Ausdrücke. Dieser Artikel enthält weitere Beispiele, in denen Ausdrücke in einem bestimmten Kontext weggelassen werden können, wenn ein geeigneter Ausdruck durch den Compiler abgeleitet werden kann.