Tuple Types

A tuple is a well-defined group of values of specific types that can be handled together as a single grouped value, and also be taken apart into their individual values easily. Tuples provide a more lightweight way to group related values without the need of declaring, for example, an explicit Record type.

A tuple type is expressed with the tuple of keywords, followed by a list of two or more types (since a tuple of just one value makes very little sense).

method ExtractValues(s: String): tuple of (String, Integer);

The method declared above would return a tuple consisting of a String and an Integer.

A tuple value can be constructed simply by providing a matching set of values surrounded by parentheses. The following result assignment would work for the above method.

result := ("A String", 5);

Tuple values can be assigned in whole or as their individual parts, both when assigning from a tuple or to one:

var t: tuple of (String, Int);
var s: String := "Hello"
var i: Integer := 5;

t := (s, i); // assigning individual values to a tuple
var u := t; // assigning one tuple to another
(s, i) := ExtractValues("Test"); // assigning a tuple back to individual elements

Extracting a tuple back to individual items can even be combined with a var Statement, to declare new variables for the items:

var t := ExtractValues("Test"); 
var (a, b) := ExtractValues("Test"); // assigning a tuple back to individual elements

Here, three new variables are declared. For the first call, t is declared as new tuple variable, so far so unusual. For the second call though, two new variables a and b are declared, and the tuple is automatically taken apart, so that a would hold the String value and b the Integer.

Tuples and Discardable

Tuple extraction can also be combined with a [Discardable] Expression(../Expressions/Discardable). If only some of the values of a tuple are of interest, the nil keyword can be provided in place of the items that are not of interest, and the will be discarded.

var (FirstName, nil, Age) := GetFirstNameLastNameAndAge();

Here, assuming that GetFirstNameLastNameAndAge returns a tuple of three values of information about a person, but only two variables are declared, for the FirstName and Age, the middle value of the tuple is simply discarded.

Accessing Individual Tuple Items

Instead of extracting the whole tuple, individual values inside a tuple can also be accessed directly, with the Indexer Expression:

var Info := GetFirstNameLastNameAndAge();
writeLn($"{Info[0]} is {Info[2]" years old".)

While in syntax this access looks like an array access, the access to to each item of the tuple is strongly typed, so Info[0] is treated as a String, and Info[2] as an Integer, for this example. For this reason, a tuple can only be indexed with a constant index.

Named Tuples

Tuples can optionally be defined to provide names for their values. Either all or none of the values need to have a name, a tuple cannot be "partially named". A named tuple can be initialized with a tuple literal with or without names.

var Person: tuple of (Name: String, Age: Integer);
Person := (Name := "Peter", Age := 25);
Person := ("Paul", 37);

In a named tuple, individual items can be accessed both via index as outlined above, and via name:

writeLn($"{Person.Name} is {Person[1]" years old".)

Named and unnamed tuples (and tuples with mismatched names) are assignment compatible, as long as the types of the tuple items matches.

var Person: tuple of (Name: String, Age: Integer);
var Person2: tuple of (String, Integer);
Person := Person2;
Person2 := Person;

See Also