The classic “look at each element and the next one” loop is a panic waiting to happen: 0..v.len() - 1 underflows the moment the slice is empty. windows hands you every consecutive pair safely, no arithmetic required.
Whenever you need to look at neighbouring elements — deltas between samples, “is each one bigger than the last”, spotting a transition — the reflex is to index by hand:
1
2
3
4
5
6
| let v = [3, 7, 2, 9];
for i in 0..v.len() - 1 {
let diff = v[i + 1] - v[i];
// ...
}
|
This works until v is empty. v.len() is 0, v.len() - 1 underflows on usize, and the loop panics before it even starts. You end up bolting on an if !v.is_empty() guard, and the v[i + 1] indexing still pays a bounds check every iteration.
slice::windows(n) gives you an iterator of overlapping sub-slices of length n. Ask for 2 and you get each consecutive pair, with no index juggling and no empty-slice trap:
1
2
3
4
5
6
7
| let v = [3, 7, 2, 9];
let diffs: Vec<i32> = v.windows(2)
.map(|w| w[1] - w[0])
.collect();
assert_eq!(diffs, vec![4, -5, 7]);
|
Because windows yields nothing when the slice is shorter than n, the empty and single-element cases just fall out for free — no special handling:
1
2
3
4
5
| let empty: [i32; 0] = [];
assert_eq!(empty.windows(2).count(), 0);
let one = [42];
assert_eq!(one.windows(2).count(), 0);
|
It composes with the rest of the iterator toolbox, too. Checking that a slice is strictly increasing becomes one readable line:
1
2
3
| let v = [1, 4, 6, 10];
let strictly_increasing = v.windows(2).all(|w| w[0] < w[1]);
assert!(strictly_increasing);
|
The window size isn’t limited to 2 — pass 3 for sliding triples (handy for smoothing or peak detection), and each window is a real slice you can index, sum, or pattern-match:
1
2
3
| let v = [1, 2, 3, 4, 5];
let sums: Vec<i32> = v.windows(3).map(|w| w.iter().sum()).collect();
assert_eq!(sums, vec![6, 9, 12]);
|
One caveat: the windows overlap and share elements, so windows only hands out shared (&) references — you can’t mutate through them. When you want non-overlapping fixed-size groups instead, reach for chunks. But for anything that compares an element to its neighbours, windows replaces the fragile len() - 1 loop with code that can’t go out of bounds.