Slices
A slice gives you a view into a larger collection:
fn main() { let a: [i32; 6] = [10, 20, 30, 40, 50, 60]; println!("a: {a:?}"); let s: &[i32] = &a[2..4]; println!("s: {s:?}"); }
- Slices borrow data from the sliced type.
- Question: What happens if you modify
a[3]?
-
We create a slice by borrowing
aand specifying the starting and ending indexes in brackets. -
If the slice starts at index 0, Rust’s range syntax allows us to drop the starting index, meaning that
&a[0..a.len()]and&a[..a.len()]are identical. -
The same is true for the last index, so
&a[2..a.len()]and&a[2..]are identical. -
To easily create a slice of the full array, we can therefore use
&a[..]. -
sis a reference to a slice ofi32s. Notice that the type ofs(&[i32]) no longer mentions the array length. This allows us to perform computation on slices of different sizes. -
Slices always borrow from another object. In this example,
ahas to remain ‘alive’ (in scope) for at least as long as our slice. -
The question about modifying
a[3]can spark an interesting discussion, but the answer is that for memory safety reasons you cannot do it throughaafter you created a slice, but you can read the data from bothaandssafely. More details will be explained in the borrow checker section.// We cannot change a[3] after it has been borrowed by s. fn main() { let mut a: [i32; 6] = [10, 20, 30, 40, 50, 60]; println!("a: {a:?}"); let s: &mut [i32] = &mut a[2..4]; s[0] = 1; println!("s: {s:?}"); } // but we can still read the content of a fn main() { let mut a: [i32; 6] = [10, 20, 30, 40, 50, 60]; println!("a: {a:?}"); let s: &mut [i32] = &mut a[2..4]; s[0] = 1; println!("a: {a:?}"); }