Return 值如果通过谓词,否则默认

Return value if passes predicate, else default

如果某个值未通过谓词,我如何替换该值?

举例说明:

assert_eq!((3-5).but_if(|v| v < 0).then(0), 0)

我以为 OptionResult 上会有一些允许这样做的东西,但我找不到它。

I thought there would be something on Option or Result

但这两种类型都没有出现在这里。两个数相减得到另一个数。

看来您只需要一个传统的 if-else 语句:

fn main() {
    let a = 3 - 5;
    assert_eq!(if a < 0 { 0 } else { a }, 0);
}

由于您有两个可以比较的值,您可能也对max感兴趣:

use std::cmp::max;

fn main() {
    assert_eq!(max(0, 3 - 5), 0);
}

可以使您提出的语法有效,但我不确定它是否值得。提交时未作进一步评论...

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
        }
    }
}

更新: 添加了 Rust 1.27, when Option::filter 后变得更好了:

assert_eq!(Some(3 - 5).filter(|&v| v >= 0).unwrap_or(0), 0);

在 Rust 1.27 之前,您需要一个迭代器才能编写单个链式表达式,而无需大量额外的自定义机制:

assert_eq!(Some(3 - 5).into_iter().filter(|&v| v >= 0).next().unwrap_or(0), 0);