I just saw the following change in a pull request:
- .ok_or(Error::new(ErrorKind::Other, "Decode error"));
+ .ok_or_else(|| Error::new(ErrorKind::Other, "Decode error"));
The only differences I know are:
ok_or
we have already created Error
by Error::new
and passed it into a adaptor.ok_or_else
we have passed a closure which will produce such a value but it may not be called if there is Some
data in the Option
.Did I miss anything?
The primary reason to use ok_or_else
or any of the ..._or_else
methods is to avoid executing a function when it's not needed. In the case of Option::ok_or_else
or Option::unwrap_or_else
, there's no need to run extra code when the Option
is Some
. This can make code faster, depending on what happens in the error case
In this example, Error::new
likely performs allocation, but it could also write to standard out, make a network request, or anything any piece of Rust code can do; it's hard to tell from the outside. It's generally safer to place such code in a closure so you don't have to worry about extraneous side effects when the success case happens.
Clippy lints this for you as well:
fn main() {
let foo = None;
foo.unwrap_or("hello".to_string());
}
warning: use of `unwrap_or` followed by a function call
--> src/main.rs:3:9
|
3 | foo.unwrap_or("hello".to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "hello".to_string())`
|
= note: `#[warn(clippy::or_fun_call)]` on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call
In addition to performance implications, more complex arguments in ok_or
might yield unexpected results if one is not careful enough; consider the following case:
fn main() {
let value: Option<usize> = Some(1);
let result = value.ok_or({ println!("value is not Some!"); 0 }); // actually, it is
assert_eq!(result, Ok(1)); // this holds, but "value is not Some!" was printed
}
This would have been avoided with ok_or_else
(and the same goes for other *_or_else
functions), because the closure is not evaluated if the variant is Some
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With