liveBook · Manning

Slicing

As explained in Learn Rust in a Month of Lunches

A slice is a dynamically sized borrowed view of a contiguous sequence of values.

A slice is a borrowed view of part or all of a sequence. It lets you work with a piece of an array without making that piece a new array. The `&` marks the borrow: a slice can have different lengths, so Rust uses a reference rather than storing it as a local value of unknown size. section 3.1.1

Take a piece of an array

Given `let numbers = [0, 1, 2, 3, 4, 5];`, write `let piece = &numbers[2..5];`. The result is `[2, 3, 4]`: indexes start at zero, and `2..5` stops before index 5. Use `2..=5` when you want to include index 5. section 3.1.1

fn main() {
    let array_of_ten = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
 
    let two_to_five = &array_of_ten[2..5];     #1
    let start_at_one = &array_of_ten[1..];     #2
    let end_at_five = &array_of_ten[..5];      #3
    let everything = &array_of_ten[..];        #4
 
    println!("Two to five: {two_to_five:?},
Start at one: {start_at_one:?},
End at five: {end_at_five:?},
Everything: {everything:?}");
}

Compare `2..5`, `1..`, `..5`, and `..` on the same array. Leaving out a range endpoint extends the slice to that end of the array. section 3.1.1

A string slice, `&str`, is another borrowed view. It has a pointer to string data and a length, so it may refer to only part of data owned elsewhere. `String`, by contrast, owns its data and can grow or shrink. A plain `str` can have different lengths; if a local variable is declared as `str`, the compiler suggests borrowing it as `&str` instead. section 2.2

How long the borrowed data lasts matters. A string literal has type `&'static str` and lasts for the whole program. A `&str` borrowed from a `String` depends on that `String`: a function cannot return a slice borrowed from a `String` that dies when the function ends. A function taking `&str` can also accept `&String`, which Rust converts for the call. section 10.1 section 10.2.1

Slices are useful beyond handwritten ranges. Calling `.chunks(3)` on a vector visits consecutive pieces, including a shorter final piece; `.windows(3)` visits overlapping pieces. A vector’s `.split_at()` gives two slices while leaving the vector intact, and `.split_at_mut()` gives pieces whose values can be changed. section 9.1.4 section 20.7

fn main() {
    let num_vec = vec![1, 2, 3, 4, 5, 6, 7];
 
    for chunk in num_vec.chunks(3) {
        println!("{:?}", chunk);
    }
    println!();
    for window in num_vec.windows(3) {
        println!("{:?}", window);
    }
}

The loops show the difference: chunks of three advance to the next piece, while windows of three advance one item at a time. section 9.1.4

How Learn Rust in a Month of Lunches covers it

How deep it goes
Explains range endpoints, variable-sized slices, ownership, and borrowed-string lifetimes through examples and compiler feedback.
Examples
Shows array-range outputs, a compiler correction from `str` to `&str`, and vector chunks and windows.
What it assumes
Introduces indexes, exclusive endpoints, references, and dynamically sized slices while building on arrays and borrowing.
What you can do after
Practice/perform array slicing with ranges and choose chunks, windows, or vector splitting for borrowed pieces.
How it connects
Links slicing to references, ownership, ranges, string literals, lifetimes, vectors, and iterators.

Also explained in

Compare how 16 books explain slicing →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.