patternrustCritical
What is this question mark operator about?
Viewed 0 times
aboutmarkthisoperatorwhatquestion
Problem
I'm reading the documentation for
What is the
File://..
let mut file = File::create("foo.txt")?;
//..What is the
? in this line? I do not recall seeing it in the Rust Book before.Solution
As you may have noticed, Rust does not have exceptions. It has panics, but their use for error-handling is discouraged (they are meant for unrecoverable errors).
In Rust, error handling uses
This is great because:
It's less than ideal, however, in that it is very verbose. This is where the question mark operator
The above can be rewritten as:
which is much more concise.
What
It's a bit magic, but error handling needs some magic to cut down the boilerplate, and unlike exceptions it is immediately visible which function calls may or may not error out: those that are adorned with
One example of the magic is that this also works for
The
See also:
In Rust, error handling uses
Result. A typical example would be:fn halves_if_even(i: i32) -> Result {
if i % 2 == 0 {
Ok(i / 2)
} else {
Err(/* something */)
}
}
fn do_the_thing(i: i32) -> Result {
let i = match halves_if_even(i) {
Ok(i) => i,
Err(e) => return Err(e),
};
// use `i`
}This is great because:
- when writing the code you cannot accidentally forget to deal with the error,
- when reading the code you can immediately see that there is a potential for error right here.
It's less than ideal, however, in that it is very verbose. This is where the question mark operator
? comes in.The above can be rewritten as:
fn do_the_thing(i: i32) -> Result {
let i = halves_if_even(i)?;
// use `i`
}which is much more concise.
What
? does here is equivalent to the match statement above with an addition. In short:- It unpacks the
Resultif OK
- It returns the error if not, calling
From::fromon the error value to potentially convert it to another type.
It's a bit magic, but error handling needs some magic to cut down the boilerplate, and unlike exceptions it is immediately visible which function calls may or may not error out: those that are adorned with
?.One example of the magic is that this also works for
Option:// Assume
// fn halves_if_even(i: i32) -> Option
fn do_the_thing(i: i32) -> Option {
let i = halves_if_even(i)?;
// use `i`
}The
? operator, stabilized in Rust version 1.13.0 is powered by the (unstable) Try trait.See also:
- Is the question mark operator ? equivalent to the try! macro?
- Why do try!() and ? not compile when used in a function that doesn't return Option or Result?
Code Snippets
fn halves_if_even(i: i32) -> Result<i32, Error> {
if i % 2 == 0 {
Ok(i / 2)
} else {
Err(/* something */)
}
}
fn do_the_thing(i: i32) -> Result<i32, Error> {
let i = match halves_if_even(i) {
Ok(i) => i,
Err(e) => return Err(e),
};
// use `i`
}fn do_the_thing(i: i32) -> Result<i32, Error> {
let i = halves_if_even(i)?;
// use `i`
}// Assume
// fn halves_if_even(i: i32) -> Option<i32>
fn do_the_thing(i: i32) -> Option<i32> {
let i = halves_if_even(i)?;
// use `i`
}Context
Stack Overflow Q#42917566, score: 402
Revisions (0)
No revisions yet.