sunface / rust-by-practice

Learning Rust By Practice, narrowing the gap between beginner and skilled-dev through challenging examples, exercises and projects.
https://practice.course.rs
Creative Commons Attribution 4.0 International
12.24k stars 985 forks source link

Fix Mutable slice content in Collection Types -> Vector -> Slicing #524

Closed mckzm closed 4 months ago

mckzm commented 4 months ago

At present the content on slices in Collection Types -> Vector -> Slicing[0][1][2] is inaccurate with respect to mutable slices: it says that slices are read-only, but that is not the case. A mutable slice of a Vec can be taken, then mutated, which will affect the slice itself as well as its underlying Vec.

The immediate reason the code below, excerpted from exercise 5 (with the slice's ending index fixed: 3 -> 4), does not work, is that the push() method is not defined for slice3's type (&mut [i32]):


    let vec_ref: &mut Vec<i32> = &mut v;
    (*vec_ref).push(4);
    let slice3 = &mut v[0..4];
    slice3.push(4);

this is explained by the error the compiler reports:

Compiling playground v0.0.1 (/playground)
error[E0599]: no method named `push` found for mutable reference `&mut [i32]` in the current scope
  --> src/main.rs:18:12
   |
18 |     slice3.push(4);
   |            ^^^^ method not found in `&mut [i32]`

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground` (bin "playground") due to 1 previous error

We can instead, however, mutate a mutable slice by indexing into it, for example:


fn main() {
    let mut v = vec![1, 2, 3];

    let vec_ref: &mut Vec<i32> = &mut v;
    (*vec_ref).push(4);
    let slice3 = &mut v[0..4];

    //slice3 is a mutable reference, so the code below
    // will also mutate the underlying Vec
    slice3[3] = 42;

    // we need to print slice3 and v in that order,
    // since a live mutable borrow (in this case slice3) prevents the use
    // of the value it borrowed from (v)
    println!("{:?}", slice3); // prints [1, 2, 3, 42]
    println!("{:?}", v); // prints [1, 2, 3, 42]
}

I made edits to en/src/collections/vector.md and solutions/collections/Vector.md to try and reflect what I wrote above, while preserving the point I think the section was trying to make, about the advantages of passing in immutable slices rather than Vecs as arguments to functions.


[0] English URL: https://practice.course.rs/collections/vector.html#slicing [1] the code starts at: https://github.com/sunface/rust-by-practice/blob/9fb657287ff9c460de179e580c7c8a17ae60c51d/en/src/collections/vector.md?plain=1#L113 [2] the code of the matching solution starts at https://github.com/sunface/rust-by-practice/blob/9fb657287ff9c460de179e580c7c8a17ae60c51d/solutions/collections/Vector.md?plain=1#L151