How can I replace a value if it fails a predicate?
To illustrate:
assert_eq!((3-5).but_if(|v| v < 0).then(0), 0)
I thought there would be something on Option
or Result
to allow this, but I cannot find it.
How can I replace a value if it fails a predicate?
To illustrate:
assert_eq!((3-5).but_if(|v| v < 0).then(0), 0)
I thought there would be something on Option
or Result
to allow this, but I cannot find it.
I thought there would be something on
Option
orResult
But neither of these types appear here. Subtracting two numbers yields another number.
It appears you just want a traditional if-else statement:
fn main() {
let a = 3 - 5;
assert_eq!(if a < 0 { 0 } else { a }, 0);
}
Since you have two values that can be compared, you may also be interested in max
:
use std::cmp::max;
fn main() {
assert_eq!(max(0, 3 - 5), 0);
}
You can make your proposed syntax work, but I'm not sure it's worth it. Presented without further comment...
fn main() {
assert_eq!((3 - 5).but_if(|&v| v < 0).then(0), 0)
}
trait ButIf: Sized {
fn but_if<F>(self, f: F) -> ButIfTail<Self>
where F: FnOnce(&Self) -> bool;
}
// or `impl<T> ButIf for T {` for maximum flexibility
impl ButIf for i32 {
fn but_if<F>(self, f: F) -> ButIfTail<Self>
where F: FnOnce(&Self) -> bool,
{
ButIfTail(f(&self), self)
}
}
struct ButIfTail<T>(bool, T);
impl<T> ButIfTail<T> {
fn then(self, alt: T) -> T {
if self.0 {
alt
} else {
self.1
}
}
}
Update: This got a bit nicer since Rust 1.27, when Option::filter
was added:
assert_eq!(Some(3 - 5).filter(|&v| v >= 0).unwrap_or(0), 0);
Prior to Rust 1.27, you would have needed an iterator in order to write a single, chained expression without lots of additional custom machinery:
assert_eq!(Some(3 - 5).into_iter().filter(|&v| v >= 0).next().unwrap_or(0), 0);