3.4 KiB
% Arrays, Vectors, and Slices
Like many programming languages, Rust has list types to represent a sequence of things. The most basic is the array, a fixed-size list of elements of the same type. By default, arrays are immutable.
let a = [1, 2, 3]; // a: [i32; 3]
let mut m = [1, 2, 3]; // mut m: [i32; 3]
There's a shorthand for initializing each element of an array to the same
value. In this example, each element of a
will be initialized to 0
:
let a = [0; 20]; // a: [i32; 20]
Arrays have type [T; N]
. We'll talk about this T
notation later, when we
cover generics.
You can get the number of elements in an array a
with a.len()
, and use
a.iter()
to iterate over them with a for loop. This code will print each
number in order:
let a = [1, 2, 3];
println!("a has {} elements", a.len());
for e in a.iter() {
println!("{}", e);
}
You can access a particular element of an array with subscript notation:
let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3]
println!("The second name is: {}", names[1]);
Subscripts start at zero, like in most programming languages, so the first name
is names[0]
and the second name is names[1]
. The above example prints
The second name is: Brian
. If you try to use a subscript that is not in the
array, you will get an error: array access is bounds-checked at run-time. Such
errant access is the source of many bugs in other systems programming
languages.
A vector is a dynamic or "growable" array, implemented as the standard
library type Vec<T>
(we'll talk about what the <T>
means
later). Vectors always allocate their data on the heap. Vectors are to slices
what String
is to &str
. You can create them with the vec!
macro:
let v = vec![1, 2, 3]; // v: Vec<i32>
(Notice that unlike the println!
macro we've used in the past, we use square
brackets []
with vec!
. Rust allows you to use either in either situation,
this is just convention.)
There's an alternate form of vec!
for repeating an initial value:
let v = vec![0; 10]; // ten zeroes
You can get the length of, iterate over, and subscript vectors just like arrays. In addition, (mutable) vectors can grow automatically:
let mut nums = vec![1, 2, 3]; // mut nums: Vec<i32>
nums.push(4);
println!("The length of nums is now {}", nums.len()); // Prints 4
Vectors have many more useful methods.
A slice is a reference to (or "view" into) an array. They are useful for allowing safe, efficient access to a portion of an array without copying. For example, you might want to reference just one line of a file read into memory. By nature, a slice is not created directly, but from an existing variable. Slices have a length, can be mutable or not, and in many ways behave like arrays:
let a = [0, 1, 2, 3, 4];
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
for e in middle.iter() {
println!("{}", e); // Prints 1, 2, 3
}
You can also take a slice of a vector, String
, or &str
, because they are
backed by arrays. Slices have type &[T]
, which we'll talk about when we cover
generics.
We have now learned all of the most basic Rust concepts. We're ready to start building ourselves a guessing game, we just need to know one last thing: how to get input from the keyboard. You can't have a guessing game without the ability to guess!