We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Closures and Iterators step 10 of 28
fold and try_fold: a total that refuses to overflow
Implement two functions over a list of i64 values:
pub fn checked_total(nums: Vec<i64>) -> Option<i64>
pub fn running_max(nums: Vec<i64>) -> Vec<i64>
checked_total starts at zero and adds values from left to right.
Return Some(total) if every addition fits in i64, or None at the first
overflow in either direction. Empty input returns Some(0).
Check every intermediate total, not just the final mathematical sum.
[i64::MAX, 1, -1] returns None: the second addition overflows even though
the final mathematical sum would fit. A single i64::MIN or i64::MAX is
valid and returns Some of that value.
running_max returns the largest value seen through each position,
including the current value. It always returns one entry per input value,
independently of whether checked_total fails.
| Input | Checked total | Running maxima |
|---|---|---|
[3, 1, 4, 1, 5] |
Some(14) |
[3, 3, 4, 4, 5] |
[-1, -2] |
Some(-3) |
[-1, -1] |
[] |
Some(0) |
[] |
[i64::MAX, 1] |
None |
[i64::MAX, i64::MAX] |
Use try_fold with checked addition for the total, and fold with a
Vec<i64> accumulator for the running maxima. Inputs may contain any i64
values, including duplicates; output vectors fit in memory.
Check addition explicitly
checked_add returns Some(sum) when the result fits, and None otherwise.
Its overflow behavior is the same in debug and optimized builds.
Ordinary integer + does not implement this contract. Depending on overflow
checks, it can panic or wrap instead of returning None. Optimization and
overflow checks are separate compiler settings: -O alone does not rule
out explicitly enabled checks. An ordinary sum::<i64>() does not report
overflow as Option either.
Accumulate, or stop early
fold(init, f) passes an accumulator through the iterator in order. Each
call receives the previous accumulator and the next item, then returns the
new accumulator. On empty input it returns init. The accumulator type can
differ from the item type, as it does for the vector in running_max.
try_fold lets a step signal failure. With Option, each successful step
returns Some(next_accumulator); None stops the fold immediately. With
Result, the corresponding outcomes are Ok(next_accumulator) and Err.
Empty input returns Some(init) or Ok(init), according to the chosen type.
Here, acc.checked_add(x) already has the required Option<i64> shape.
Use an i64 initial value so the accumulator's type is clear.
This complete example also shows how a named iterator can resume after a failed step. The item that caused failure has been consumed:
fn main() {
let mut values = [i64::MAX, 1, -1].into_iter();
let total = values.try_fold(0_i64, |acc, x| acc.checked_add(x));
assert_eq!(total, None);
assert_eq!(values.next(), Some(-1));
}
reduce is another option for an accumulator of the same type as the items:
it uses the first item as its starting value and returns None when empty.
Integer sum and product have empty results of zero and one, respectively.
These methods do not all share one initialization rule; sum is defined
through the Sum trait, not through Default.
Build the running maxima
Start the fold with an empty vector. For each value, compare it with the vector's last entry, push the larger one, and return the vector for the next step. When no previous entry exists, use the current input itself. Starting with zero would give wrong results for an all-negative input.
The starter's ordinary addition fold is also flagged by Clippy's
unnecessary_fold lint. Replacing it with sum addresses that style issue
but leaves the overflow contract unsatisfied. Use the required checked fold.
Your solution must compile, use the requested folds, match both outputs and pass Clippy with warnings treated as errors.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.