Tuples group values with a variety of types.
Arrays group values of a single type.
They both have a fixed size.
While arrays are less flexible in content, they are more flexible in usage.
The array and the tuple are both compound types, that means they can hold multiple values.
An array and a tuple are both groups of other values.
Tuples are enclosed by parentheses ()
.
Every element in it is separated by a comma ,
.
Arrays are enclosed by square braces []
.
Every element in it is separated by a comma ,
.
They are both fixed in size, they can't shrink or grow.
A vector is a similar collection type that is allowed to change in size.
So far, they sound very similar, with just some arbitrary syntax differentiating them.
Types
For an array, every item in that group has to have the same type.
If a value in that array is of type f64
, every item in that array must be of type f64
.
let arr = [1.0, 2.5, 3.14];
For tuples, items in that group can have different types.
All values in a tuple can be the same type, but they can be different too.
let tup = (1, 2.5, "yummy pie");
Annotating the types
The Rust compiler is smart and will try to figure out which types it's dealing with, that means explicit type declarations are not always needed.
For arrays, the type declaration consists of enclosing square brackets. Inside is the type of the elements followed by a semicolon ;
, and the length or the array.
let arr: [f64;3] = [1.0, 2.5, 3.14];
For tuples, the type declaration consists of enclosing parentheses. Inside are the types of each element, each one separated by a comma ,
.
let tup: (i32, f64, &str) = (1, 2.5, "yummy pie");
Accessing information
Element by index
Indexes for both tuples and arrays start at 0.
Tuples, somewhat surprisingly, use the .
to access an element at a specific index.
let first_arr = arr[0]; // 1.0
let first_tup = tup.0; // 1
Element by destructuring
let (tup_first, tup_second, tup_third) = tup;
let [arr_first, arr_second, arr_third] = arr;
println!("tup_first: {}, tup_second: {}, tup_third: {}", tup_first, tup_second, tup_third);
// tup_first: 1, tup_second: 2.5, tup_third: "yummy pie"
println!("arr_first: {}, arr_second: {}, arr_third: {}", arr_first, arr_second, arr_third);
// arr_first: 1.0, arr_second: 2.5, arr_third: 3.14
It's a lot more common to destructure tuples.
It's especially handy if a function returns 2 values in a tuple and you want to name each value individually.
fn num_and_double(num: i32) -> (i32, i32) {
(num, num * 2)
}
let (lucky_num, double_lucky_num) = num_and_double(3);
Length
An array has some metadata associated with it, like its length.
A tuple does not.
Tuples are essentialy structs with anonymous field names.
let arr_len = arr.len(); // 3
// let tup_len = tup.len(); // error
Looping
Iterating over a tuple doesn't work.
For a tuple, each iteration could result in a different type, that doesn’t work.
Since arrays can only hold a single type, they don't have that limitation.
// for num in &tup {
// println!("num: {}", num);
// }
// error
for num in &arr {
println!("num: {}", num);
}
// num: 1.0
// num: 2.5
// num: 3.14
Ok, fine. I'll iterate over a number range and access each item in the tuple via the dot synt...NOPE
Tuples can’t be dynamically indexed.
The compiler needs to be able to figure out what type every value is, indexing into it with a variable makes this impossible.
If the compiler doesn't know which index is being used, it can not figure out what type the value at that index is.
Here’s an (slightly contrived) example of why you can’t do stuff like that in Rust:
let myTuple = (1, 2, "false"); let x = randomNumberGenerator(); let y = myTuple.x;
In this case, the compiler wouldn’t be able to figure out at compile-time what type y should be!
— 17cupsofcoffee
Whereas with an array, you know (and the compiler knows) that indexing is always going to return the same type.
let index = 2;
let arr_pi = arr[2]; // 3.14
let also_arr_pi = arr[index]; // 3.14
let tup_pie = tup.2; // "yummy pie"
// let also_tup_pie = tup.index; // error
Code summary
fn main() {
let tup = (1,2,3);
let arr = [1,2,3];
let index = 2;
println!("Array: {:?}", arr[2]); // Array: 3
println!("Array: {:?}", arr[index]); // Array: 3
println!("Tuple: {:?}", tup.2); // Tuple: 3
// println!("Tuple: {:?}", tup.index); // error
for num in &arr {
println!("num: {}", num);
}
// num: 1
// num: 2
// num: 3
// for num in &tup {
// println!("num: {}", num);
// }
// error
let (tup_first, tup_second, tup_third) = tup;
let [arr_first, arr_second, arr_third] = arr;
println!("tup_first: {}, tup_second: {}, tup_third: {}", tup_first, tup_second, tup_third);
// tup_first: 1, tup_second: 2, tup_third: 3
println!("arr_first: {}, arr_second: {}, arr_third: {}", arr_first, arr_second, arr_third);
// arr_first: 1, arr_second: 2, arr_third: 3
// tup.len() // error
arr.len() // 3
}
Top comments (0)