【问题标题】:Return value if passes predicate, else default如果通过谓词返回值,否则默认
【发布时间】:2016-12-29 17:36:41
【问题描述】:

如果一个谓词失败,我如何替换一个值?

举例说明:

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

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

【问题讨论】:

    标签: rust optional predicate


    【解决方案1】:

    我以为OptionResult 上会有什么东西

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

    看来您只需要传统的 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
            }
        }
    }
    

    【讨论】:

    • 天哪。太多抽象的错误处理。我忘记了如何使用 if-else 语句。 -_-
    • 感谢您让我的大脑放屁并与它一起奔跑。优秀的答案。 :)
    【解决方案2】:

    更新:自从Rust 1.27 添加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);
    

    【讨论】:

      猜你喜欢
      • 2018-12-12
      • 2013-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-12
      • 1970-01-01
      • 2013-02-25
      • 1970-01-01
      相关资源
      最近更新 更多