Ein Tupel ist eine Gruppierung von zwei oder mehr Ausdrücken, die wie ein einzelner Ausdruck behandelt wird.
Ein Tupel literal hat zwischen „()“ mehrere Ausdrücke, wobei die Elemente durch Kommas getrennt sind:
(1, 2, 3)
Die Reihenfolge der Elemente in einem Tupel ist wichtig. Das folgende Tupel unterscheidet sich vom vorherigen Tupel-Beispiel:
(3, 2, 1)
Der gleiche Ausdruck kann auch an mehreren Stellen in einem Tupel sein:
(„Hilf mir Rhonda“, „Hilfe“, „Hilf mir Rhonda“)
Tupel-Ausdrücke können von jedem Typ sein und gemischte Typen enthalten (im Gegensatz zu Arrays, die nur Elemente eines Typs haben können):
(1, 2.0, "three")
Tupel können sogar andere Tupel enthalten:
(1, (10, 20.0, "thirty"), "three")
Wenn du mit diesen Begriffen vertraut bist, ist ein Tupel wie folgt:
- Eine unbenannte Datenstruktur mit unbenannten geordneten Elementen
- Ein Array mit fester Größe, bei der jedes Element ein anderer Typ sein kann
Tupel sind besonders nützlich für Folgendes:
- Rückgabe mehrerer Werte aus einer Funktion.
- Eine einfache direkte Gruppierung, die kurzgefasster ist als der Aufwand, eine vollständig beschriebene, wiederverwendbare Datenstruktur (z. B. eine Struktur oder Klasse) zu erstellen.
Spezifizieren einer Variablen mit einem Tupel-Typ
Um den Variablen-Typ als Tupel zu spezifizieren, wird das Präfix „Tupel“ vor durch Komma getrennten Typen verwendet, die in „()“ eingeschlossen sind:
MyTupleInts : tuple(int, int, int) = (1, 2, 3)
MyTupleMixed : tuple(int, float, string) = (1, 2.0, "three")
MyTupleNested : tuple(int, tuple(int, float, string), string) = (1, (10, 20.0, "thirty"), "three")
Tupeltypen können auch [gefolgert] werden (vers-glossary#infer):
MyTupleInts := (1, 2, 3)
MyTupleMixed := (1, 2.0, "three")
MyTupleNested := (1, (10, 20.0, "thirty"), "three")
Tupel-Typen Spezifizierer können in Daten Untersätzen und Funktionstypsignaturen für Parameter oder einen Rückgabe-Typ verwendet werden:
ExampleFunction(Param1 : tuple(string, int), Param2 : tuple(int, string)) : tuple(string, int) =
# Parameter als Ergebnis verwenden
Param1
Tupel Element-Zugriff
Auf die Elemente eines Tupels kann mit einem nicht fehlerhaften, nullbasierten Index Operator zugegriffen werden, der eine Ganzzahl übernimmt. Der Indexoperator kann nicht fehlschlagen (im Gegensatz zu einem Matrix-Indexoperator „[index]“, der fehlschlagen kann), da der Compiler immer die Anzahl der Elemente aller Tupel kennt und daher jeder Index außerhalb der Grenzen ein Fehler der Kompilierzeit sein wird:
MyTuple := (1, 2.0, "three")
MyNestedTuple := (1, (10, 20.0, "thirty"), "three")
var MyInt: int = MyTuple(0)
var MyFloat: float = MyTuple(1)
var MyString: string = MyTuple(2)
Print("Meine Variablen: {MyInt}, {MyFloat}, {MyString}")
Print("Mein verschachteltes Tupel-Element: {MyNestedTuple(1)(2)}")
Tupel-Matrix-Zwänge
Tupel können überall dort übergeben werden, wo eine Matrix erwartet wird, vorausgesetzt, dass der Typ der Tupel-Elemente alle vom gleichen Typ wie die Matrix ist. Matrizen können nicht übergeben werden, wenn ein Tupel erwartet wird.
Tupel-Erweiterung
Ein Tupel, das als einzelnes Element einer Funktion übergeben wird, verhält sich so, als ob die Funktion mit jedem einzelnen Element des Tupels aufgerufen würde. Dies wird als Tupel-Erweiterung oder Splatting bezeichnet.
F(Arg1 : int, Arg2 : string) : void =
DoStuff(Arg1, Arg2)
G() : void =
MyTuple := (1, "two")
F(MyTuple(0), MyTuple(1)) # Accessing elements
F(MyTuple) # Tupel-Erweiterung
Der Ausdruck „sync“ strukturierte Gleichzeitigkeit hat ein Tupel-Ergebnis, das mehrere Argumente zulässt, die im Laufe der Zeit auswerten, um simultan ausgewertet zu werden. Weitere Informationen findest du unter Gleichzeitigkeit.
Dauerhafte Typen
Ein Tupel ist dauerhaft, wenn jeder Elementtyp in dem Tupel dauerhaft ist. Wenn ein Tupel dauerhaft ist, bedeutet das, dass du es in deiner modulbereichsbezogenen Variable weak_map verwenden kannst und die Werte dann über Spielsitzungen hinweg erhalten bleiben. Weitere Details zum Fortbestand in Verse findest du unter Verwenden dauerhafter Daten in Verse.