We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Ground Rules: Values, Types, Control Flow step 21 of 24
Slices &[T]: the shape that unifies arrays and Vec
Find the largest sum of any k consecutive elements.
pub fn max_window_sum(values: &[i32], k: usize) -> Option<i32>
Return None when no window of that size exists — when k is 0, and when
k is longer than the slice.
([1, 2, 3, 4], 2) gives Some(7). ([1], 2) gives None. ([5], 1) gives
Some(5). ([1, 2], 0) gives None.
The starter compiles and passes clippy. It panics on one of the tests, and finding out why is the exercise.
A slice is a pointer and a length
&[T] // shared slice: read many
&mut [T] // exclusive slice: write one
A &[i32] is 16 bytes on a 64-bit machine — a pointer to the first element and
a count — which makes it a fat pointer: a reference that carries extra
information about what it points at. size_of::<&[i32]>() == 16, against 8 for
an ordinary &i32.
Because it is only a view, a slice can name:
-
the whole of a
Vec:&v -
the whole of an array:
&arr -
any sub-range of either:
&v[2..7] - a string’s bytes, a boxed slice, a stack buffer…
and every function that accepts &[T] works with all of them for free. That is
what “take &[T], not &Vec<T>“ buys, stated positively.
The coercion from &Vec<T> to &[T] — and from &[T; N] to &[T] — happens
automatically, through Deref. You will almost never write it out. It is worth
knowing it is there, because it is the same machinery that lets a &String
become a &str, which is item 1.23.
windows, and the guard it needs
slice.windows(k) yields every contiguous run of k elements, overlapping,
left to right:
[1, 2, 3, 4].windows(2) // [1,2], [2,3], [3,4]
Two behaviours you must handle, and they are different:
-
If
kis larger than the slice,windowsyields nothing at all. That is not an error; the iterator is simply empty, andmax()on an empty iterator isNone. So this case already works. -
If
kis zero,windowspanics: “window size must be non-zero”. There is no sensible empty window, and the method chose to be loud rather than invent an answer.
That asymmetry is why the None guard in this function is load-bearing rather
than defensive. Add the check before you ask for windows, not after.
Its non-overlapping sibling is chunks(k), which splits into consecutive blocks
and leaves a short one at the end; chunks_exact(k) drops the remainder and is
faster. windows has no windows_exact, because every window is already exact.
Option as the return type
Returning Option<i32> rather than, say, 0 or i32::MIN is the honest
signature: “there may be no answer” is a real state of the world for an empty
input, and the type says so. Every caller is then forced to decide what to do
about it, which is the entire value proposition.
Note that Iterator::max already returns Option<T> for exactly this reason —
the maximum of nothing is not a number. So the last line of the happy path
needs no wrapping.
A note on inference
w.iter().sum() cannot be inferred on its own: sum is generic over its output
and there are several types it could produce. Either annotate the closure’s
return, or use the turbofish — sum::<i32>() — to say which. E0282: type annotations needed is what you get if you say nothing, and you met it in item
0.2.
Loading visualization…
Stuck?
Rust reference solution
Sign in to attempt this problem and reveal the reference solution.