Rust Slices
A slice is a view of part of a collection, like a window onto some of the items. It does not copy anything; it simply points at a stretch of a string, an array or a vector. You have already used one kind of slice without knowing it: &str is a string slice.
Slicing a string
You make a slice with a range in square brackets. &text[0..4] means the bytes from position 0 up to, but not including, position 4:
fn main() {
let text = String::from("Hello Rust");
let hello = &text[0..5];
let rust = &text[6..];
println!("[{}] [{}]", hello, rust);
}[Hello] [Rust]
Leaving out the start, as in [..5], means "from the beginning", and leaving out the end, as in [6..], means "to the end". The positions count bytes. For plain English text that is the same as letters; for other alphabets it is safer to use methods like chars or split, because slicing in the middle of a multi-byte character stops the program.
Why &str makes great parameters
When a function only needs to read text, the kindest type to accept is &str. It works with string literals, with a borrowed String, and with slices, all at once:
fn first_word(text: &str) -> &str {
match text.find(' ') {
Some(space) => &text[..space],
None => text,
}
}
fn main() {
let owned = String::from("good morning everyone");
println!("{}", first_word(&owned));
println!("{}", first_word("hello"));
println!("{}", first_word(&owned[5..]));
}good hello morning
The returned &str is a window into the original text, so no new text is created. Rust also makes sure the original cannot be changed or dropped while the window is still in use, which is borrowing at work again.
Slices of arrays and vectors
The same idea works for lists of numbers. A slice of numbers has the type &[i32], and functions that take one can work with arrays and vectors alike:
fn total(numbers: &[i32]) -> i32 {
let mut sum = 0;
for n in numbers {
sum += n;
}
sum
}
fn main() {
let week = [3, 5, 2, 8, 6, 9, 4];
println!("Whole week: {}", total(&week));
println!("Weekdays: {}", total(&week[..5]));
println!("Weekend: {}", total(&week[5..]));
}Whole week: 37 Weekdays: 24 Weekend: 13
If a range goes past the end, for example &week[5..10] on a list of 7 items, the program stops with a message that says so. Rust never quietly reads memory that does not belong to the list.
Practice exercises
- Print the first three letters and the last three letters of the word "programming" using slices.
- Write
fn last_word(text: &str) -> &strusingrfind(' '). - Write a function that returns the largest number in a
&[i32]slice.