The Question Mark Operator '?'
Part of the Logic & Flow section of Coddy's Rust journey — lesson 46 of 66.
When working with functions that return Result, you often need to handle errors by either dealing with them locally or passing them up to the calling function. Rust provides an elegant operator for this common pattern: the question mark operator ?.
The ? operator provides a clean way to propagate errors without writing verbose match statements. When you place ? after a Result, it automatically unwraps an Ok value or immediately returns from the current function with the Err:
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
let number = s.parse::<i32>()?; // If parsing fails, return the error
Ok(number * 2) // If successful, double the number
}This is equivalent to writing a full match statement, but much more concise. If s.parse::<i32>() returns an Ok, the ? extracts the value and assigns it to number. If it returns an Err, the ? immediately returns that error from the entire function.
The ? operator can only be used in functions that return a Result (or Option), since it needs to be able to return an error.
Challenge
EasyYou will receive two inputs. The first input is a string that should be parsed into an integer, and the second input is another string that should also be parsed into an integer. Create a function called add_numbers that takes two string slices as parameters and returns a Result<i32, std::num::ParseIntError>. Inside the function, use the ? operator to parse both strings and return their sum wrapped in Ok. Call the function with the two inputs and handle the result using match.
Requirements:
- Read the first input (first number as string) and trim whitespace
- Read the second input (second number as string) and trim whitespace
- Create a function
add_numbersthat takes two&strparameters and returnsResult<i32, std::num::ParseIntError> - Inside the function, parse the first string to
i32using the?operator - Parse the second string to
i32using the?operator - Return
Ok(sum)where sum is the addition of both parsed numbers - Call the function with the two input strings
- Use a
matchexpression to handle theResult - In the
Ok(value)arm, print:Sum: [value] - In the
Err(_)arm, print:Parsing error
Input:
- First line: A string representing a number (e.g.,
15) - Second line: A string representing another number (e.g.,
27)
Output:
- If both strings are valid numbers:
Sum: [result] - If either string cannot be parsed:
Parsing error
Cheat sheet
The question mark operator ? provides a concise way to propagate errors in functions that return Result.
When placed after a Result, the ? operator:
- Unwraps an
Okvalue and continues execution - Immediately returns an
Errfrom the current function if one occurs
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
let number = s.parse::<i32>()?; // If parsing fails, return the error
Ok(number * 2) // If successful, double the number
}The ? operator can only be used in functions that return a Result or Option type.
Try it yourself
use std::io;
// TODO: Create the add_numbers function here
// It should take two &str parameters and return Result<i32, std::num::ParseIntError>
fn main() {
// Read first input
let mut input1 = String::new();
io::stdin().read_line(&mut input1).expect("Failed to read line");
let input1 = input1.trim();
// Read second input
let mut input2 = String::new();
io::stdin().read_line(&mut input2).expect("Failed to read line");
let input2 = input2.trim();
// TODO: Call add_numbers with input1 and input2
// TODO: Use match to handle the Result
// Print "Sum: [value]" for Ok(value)
// Print "Parsing error" for Err(_)
}This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Logic & Flow
1Advanced Control Flow
The 'match' ExpressionMatching Multiple ValuesMatching RangesThe 'if let' ExpressionLoops as ExpressionsRecap - Simple Command Parser4Grouping Data with Structs
What is a Struct?Structs OverviewAccessing Struct FieldsMutable StructsStructs as Function ParametersTuple StructsRecap - Create a Book Struct7Handling Errors with 'Result'
What is a 'Result'?Using 'match' with 'Result'is_ok() and is_err()Shortcuts: unwrap and expectThe Question Mark Operator '?'Parsing Strings to NumbersRecap - Safe Division Function10Closures & Anonymous Functions
What is a Closure?Defining a Simple ClosureClosures with ParametersCapturing the EnvironmentRecap - Simple Adder Closure2Introduction to Vectors
What is a Vector?Creating a VectorAdding Elements with pushAccessing Vector ElementsIterating Over a VectorMutable IterationRemoving ElementsRecap - Basic Score Tracker5Key-Value Pairs with Hash Maps
What is a Hash Map?Creating a Hash MapInserting Key-Value PairsAccessing ValuesIterating Over a Hash MapUpdating a ValueRemoving a PairRecap - Word Counter8Project: Simple Item Inventory
Project SetupAdding an ItemChecking StockSelling an ItemPutting it all together