Tuples
A tuple groups a fixed number of values, possibly of different types, into one value without declaring a type for it. The elements have positions but no names. The type is written like the value: a parenthesized, comma-separated list.
tuple-type = "(" ")" | "(" type "," ")" | "(" type "," type { "," type } [ "," ] ")"
tuple-value = "(" ")" | "(" expression "," ")" | "(" expression "," expression { "," expression } [ "," ] ")"
let pair: (int, float64) = (1, 2.5);
let triple = ("Rux", 3, true); // (char8[..], int, bool)
let one = (5,); // a tuple of one element
A one-element tuple needs a trailing comma; (5) is just 5 in parentheses.
Elements
Elements are read by position, counting from zero: .0, .1, and so on. On a var tuple they can be assigned the same way. Tuples nest, and so do the accesses:
var point = (0, 0);
point.0 = 4;
point = (point.0, 9); // (4, 9)
let nested: (int, (char8[..], bool)) = (1, ("deep", true));
let word = nested.1.0; // "deep"
An index beyond the last element is a compile-time error: tuple index 2 is out of range for a tuple with 2 elements.
Type identity
A tuple type is its element types, in order. (int, float64) and (float64, int) are different types, and two tuples with the same element types are the same type wherever they were written — a tuple has no name to tell it apart:
error: cannot assign '(int, float64)' to '(float64, int)'
A tuple is a value. Assigning it, passing it and returning it copies every element, and the copy is independent of the original. A tuple is how a function returns several values:
func Divide(dividend: int, divisor: int) -> (int, int) {
return (dividend / divisor, dividend % divisor);
}
The usual way to use such a result is to take it apart at once, let (quotient, remainder) = Divide(17, 5);; see Destructuring.
The unit type
() is the tuple with no elements, the unit type, and its only value is also written (). It is the success type of a fallible function that produces nothing on success: ! E is exactly () ! E. A function may return () explicitly, func Reset() -> (), which is not the same as leaving out the result type; see Function declarations.
sizeof(()) is 0.
Equality
Two tuples of the same type compare with == and !=, element by element from left to right, stopping at the first difference. Every element type must support ==:
let same = (1, 'a') == (1, 'a'); // true
let differ = (1, 2) != (1, 3); // true
error: structural equality for '(int, char8[..])' is unavailable because element type 'char8[..]' has no '==' operator
Tuples have no built-in ordering. (1, 2) < (1, 3) is operator '<' is not defined for tuple '(int, int)', with the note tuples have structural equality but no built-in ordering.
Matching
A tuple pattern takes a tuple apart in a match arm and tests its elements at the same time. A match on a tuple is exhaustive when the combinations of its arms cover every value, so the four (bool, bool) combinations need no else:
func Describe(flags: (bool, bool)) -> char8[..] {
return match flags {
(true, true) => "both",
(true, false) => "first",
(false, true) => "second",
(false, false) => "neither"
};
}
See Patterns.
Tuples or structs
Both group several values. A tuple's elements are anonymous, so nothing at the use says what .1 means; a struct's are named, and the struct is a type of its own that cannot be mixed up with another of the same shape.
| A tuple fits when… | A struct fits when… |
|---|---|
| two or three values, their meaning obvious from context | more values, or meanings that need labels |
| the grouping is local, such as a function's results | the type is used across the program |
| no behaviour is attached | the type needs methods, constructors or operators |
any (int, int) will do | a Point must not be confused with a Size |
Tuples cannot be extended with methods; see Extensions.
Layout
A tuple's elements are stored in order, each at the next offset its alignment allows, like the fields of a struct: sizeof((uint8, uint32)) is 8. See Memory layout.
See also
- Destructuring — unpacking a tuple into bindings
- Structs — named fields and named types
- Patterns — tuple patterns
- Learn: Tuple, Destructure, Tuple pattern
Overview
Untagged overlapping storage with union: declaring members, building a union by naming one member, reading another as a reinterpretation, and layout.
Overview
The fixed-size array type T[N]: literals, repeated literals, value semantics, length, bounds-checked indexing, iteration, slicing and flexible tails.