Is there a combinator for returning a Result based on a boolean condition?

Viewed 448

For Option types, I frequently use the ok_or combinator to return errors like this:

let my_vec = [1,2,3];

let head = my_vec.first().cloned().ok_or(Error::MyError)?;

I am looking for a similar combinator or method to handle boolean values not Option types. For example:

let my_vec = [1,2,3];
let head = my_vec.is_empty().false_or(Error::MyError)?;

I often write matches to handle this, but it seems quite verbose:

let vec_is_ok = match my_vec.is_empty() {
    true => Err(...),
    false => Ok(())
}
vec_is_ok?;

Is there are more concise way to write this similar to the ok_or combinator that i can use on boolean values?

3 Answers

There is a method bool::then (added in Rust 1.50.0), returning an Option<T> which you can convert into a Result<T, E>.

Your example would look like this:

use std::ops::Not;

my_vec.is_empty().not().then(|| ()).ok_or(MyError)

I often write matches to handle this, but it seems quite verbose:

let vec_is_ok = match my_vec.is_empty() {
    true => Err(...),
    false => Ok(())
}
vec_is_ok?;

if is an expression and works with booleans:

let vec_is_ok = if my_vec.is_empty() { Err(...) } else { Ok(()) };

An alternative to Peter Hall's proposition is the older but richer boolinator crate which provides direct support for the Result type e.g.

let vec_is_ok = my_vec.is_empty.not().as_result((), ...);

or

let vec_is_ok = my_vec.is_empty.not().ok_or(...)

the latter is basically the same as the former special-cased for the "success" case of Ok(()) as that's common.

There's also as_result_from which takes two callbacks, if one (or both) payload requires expensive setup.

Related