rust/src/doc/trpl/tuples.md
2015-04-07 22:16:02 -04:00

2.7 KiB

% Tuples

The first compound data type we're going to talk about is called the tuple. A tuple is an ordered list of fixed size. Like this:

let x = (1, "hello");

The parentheses and commas form this two-length tuple. Here's the same code, but with the type annotated:

let x: (i32, &str) = (1, "hello");

As you can see, the type of a tuple looks just like the tuple, but with each position having a type name rather than the value. Careful readers will also note that tuples are heterogeneous: we have an i32 and a &str in this tuple. You have briefly seen &str used as a type before, and we'll discuss the details of strings later. In systems programming languages, strings are a bit more complex than in other languages. For now, just read &str as a string slice, and we'll learn more soon.

You can access the fields in a tuple through a destructuring let. Here's an example:

let (x, y, z) = (1, 2, 3);

println!("x is {}", x);

Remember before when I said the left-hand side of a let statement was more powerful than just assigning a binding? Here we are. We can put a pattern on the left-hand side of the let, and if it matches up to the right-hand side, we can assign multiple bindings at once. In this case, let "destructures," or "breaks up," the tuple, and assigns the bits to three bindings.

This pattern is very powerful, and we'll see it repeated more later.

There are also a few things you can do with a tuple as a whole, without destructuring. You can assign one tuple into another, if they have the same contained types and [arity]. Tuples have the same arity when they have the same length.

let mut x = (1, 2); // x: (i32, i32)
let y = (2, 3); // y: (i32, i32)

x = y;

You can also check for equality with ==. Again, this will only compile if the tuples have the same type.

let x = (1, 2, 3);
let y = (2, 2, 4);

if x == y {
    println!("yes");
} else {
    println!("no");
}

This will print no, because some of the values aren't equal.

Note that the order of the values is considered when checking for equality, so the following example will also print no.

let x = (1, 2, 3);
let y = (2, 1, 3);

if x == y {
    println!("yes");
} else {
    println!("no");
}

One other use of tuples is to return multiple values from a function:

fn next_two(x: i32) -> (i32, i32) { (x + 1, x + 2) }

fn main() {
    let (x, y) = next_two(5);
    println!("x, y = {}, {}", x, y);
}

Even though Rust functions can only return one value, a tuple is one value, that happens to be made up of more than one value. You can also see in this example how you can destructure a pattern returned by a function, as well.