We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Shape Your Data: Structs, Enums, Pattern Matching step 15 of 26
Simplify stack control flow with pattern matching
Simplify the starter's control flow while preserving its stack operations.
pub fn drain_stack(ops: Vec<String>) -> Vec<i64>
Process commands in input order, starting with an empty stack:
- A string starting with the exact prefix
"push "parses the remaining text as i64. Push the value if parsing succeeds; otherwise skip the command. - The exact string
"clear"empties the stack. - Skip every other string.
Do not trim commands or their arguments. "push +007" pushes 7, but
"push 7", "push 7 ", "Push 7" and " push 7" do nothing.
The parser accepts decimal integers with an optional sign and leading zeros.
Empty arguments, underscores, non-ASCII digits and values outside i64 fail.
"clear " does not clear the stack.
After processing all commands, repeatedly pop the stack and append twice
each popped value to the result. Preserve duplicates. This reverses the
surviving push order: ["push 1", "push 2", "push 3"] gives [6, 4, 2].
["push 1", "clear", "push -5"] gives [-10]. Empty input, or a final clear
with no later valid push, produces an empty vector.
With the runner's current optimized execution settings, overflowing i64 multiplication wraps in 64 bits. Pushing i64::MAX then draining yields -2; pushing i64::MIN yields 0. This describes the runner's current build: checked builds instead panic on overflow. The accepted parse range is the full i64 range, not just the values whose doubles fit.
Use the construct that matches the branch
The starter produces the expected results but fails Clippy. Its one-arm matches and pop loop can be expressed more directly. A match remains useful when several patterns need different behavior; it is not inherently bad.
if let executes a branch when a pattern matches. Inside that branch,
let ... else can handle failure immediately and leave a successful binding
available in the surrounding block. This complete example skips malformed
push arguments:
fn main() {
let ops = ["push 2", "ignore", "push x", "push -3"];
let mut values = Vec::new();
for op in ops {
if let Some(rest) = op.strip_prefix("push ") {
let Ok(value) = rest.parse::<i64>() else {
continue;
};
values.push(value);
}
}
assert_eq!(values, [2, -3]);
}
Ok(value) is a refutable pattern because the parser could return Err.
The else branch must diverge: it cannot continue to the statement after
the binding. Here continue starts the next iteration. Return, an applicable
break, panic or a non-returning call can also provide divergence.
The else branch cannot supply a fallback value. This complete program is intentionally invalid and produces E0308:
fn value_or_zero(maybe: Option<i64>) -> i64 {
let Some(n) = maybe else { 0 };
n
}
fn main() {
assert_eq!(value_or_zero(None), 0);
}
If a fallback is what you want, use maybe.unwrap_or(0) or a match instead.
See the let statement rules.
Repeat while a pattern matches
This complete example drains a stack without doubling:
fn main() {
let mut stack = vec![1, 2, 3];
let mut popped = Vec::new();
while let Some(top) = stack.pop() {
popped.push(top);
}
assert_eq!(popped, [3, 2, 1]);
assert!(stack.is_empty());
}
Pop removes an element on every successful iteration, so this loop eventually receives None. More generally, a while-let loop ends when its pattern fails or control leaves the loop. Progress can happen in the condition or the body; a condition that does not itself mutate state is not necessarily an infinite loop. Check the whole loop when reasoning about termination.
Clippy's single_match and while_let_loop diagnostics identify relevant
replacements in this starter. An equality check is sufficient for clear.
Keep the required behavior rather than trying to reach a particular number
of diagnostics. Passing requires compilation, correct results 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.