We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Errors Are Values step 4 of 24
Eager vs lazy defaults
Repair resolve so it computes a fallback only for missing values. Keep the
supplied expensive helper and #![deny(clippy::or_fun_call)] unchanged.
pub fn resolve(inputs: Vec<Option<i32>>) -> (Vec<i32>, Vec<String>)
Return the resolved values and the helper's log:
- Preserve every Some value exactly, in input order, including duplicates, zero, negative numbers and the i32 limits.
- For each None, call expensive once at that point in the traversal and use its return value, -1. Do not call it for Some values or write substitute log entries yourself.
- Each helper call appends
"computed default N", where N starts at 1 and increases by one. Return the log unchanged. - Empty input returns two empty vectors. An input with no None values has an empty log.
For [Some(5), None, Some(7), None], return values [5, -1, 7, -1] and log
["computed default 1", "computed default 2"]. Some(-1) is already a value
and does not trigger the helper, even though the fallback also returns -1.
In test inputs, JSON integers represent Some values and null represents None.
Why unwrap_or calls the helper too often
The starter passes expensive(&mut log) as an argument to unwrap_or. Rust
evaluates that expression before calling the method. It therefore records
a helper call on every iteration, even when the option contains a value.
The returned values are correct, but the returned log is wrong whenever
the input contains Some.
unwrap_or_else accepts a closure. Its body runs only when the option is None. Keep the fallback computation inside that body; computing it first and returning the saved result from a closure would still do the work eagerly.
This complete example compares the two forms:
fn fallback(calls: &mut usize) -> i32 {
*calls += 1;
-1
}
fn eager(value: Option<i32>, calls: &mut usize) -> i32 {
value.unwrap_or(fallback(calls))
}
fn lazy(value: Option<i32>, calls: &mut usize) -> i32 {
value.unwrap_or_else(|| fallback(calls))
}
fn main() {
let mut calls = 0;
assert_eq!(eager(Some(7), &mut calls), 7);
assert_eq!(calls, 1);
assert_eq!(lazy(Some(7), &mut calls), 7);
assert_eq!(calls, 1);
assert_eq!(lazy(None, &mut calls), -1);
assert_eq!(calls, 2);
}
The example deliberately includes eager evaluation for comparison. With this exercise's deny attribute added, Clippy rejects the fallback call inside eager's unwrap_or. The lazy version avoids that diagnostic.
Closure creation and capture still happen when the closure expression is evaluated. Laziness here refers to running its body. In resolve, the closure borrows log mutably for the call; you can use log again afterwards.
Choose a fallback that matches the behavior you need
Use a closure when fallback work should happen only for a missing value. Side effects matter as well as cost: even a quick log update must not run for Some in this exercise.
A simple constant does not need a closure. value.unwrap_or(0) is clearer
than value.unwrap_or_else(|| 0), and Clippy's unnecessary_lazy_evaluations
lint warns about the latter. This warning becomes an error under the grader's
warnings-as-errors setting.
Not every constructor allocates. String::new and an empty Vec create empty containers without allocating storage for their elements. When the intended fallback is a type's Default value, unwrap_or_default expresses that directly and calls Default::default only for None. It would return 0 for Option<i32>, so it does not implement this exercise's -1 fallback and logging behavior.
The supplied or_fun_call lint is allow-by-default, so its explicit deny attribute matters. It catches the starter's eager function call; it is not a general proof of correct call counts. Keep expensive unchanged and check both vectors in the result.
See the Option methods for their signatures. Passing requires the expected values and log, successful compilation and 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.