早期从Rust的比赛中脱颖而出

时间:2016-06-14 14:30:53

标签: pattern-matching rust match break

我想切换x的许多可能情况以及一个案例(此处x == 0),我想检查一些其他代码的结果以确定下一步做什么。一种可能性是从比赛早期返回。

在C中,我使用break进行早期返回,遗憾的是,这是不允许的。 return从父函数(在本例中为main())返回,而不是仅从匹配中返回(即最后的println!不运行!)。

我可以否定子条件(这里是y == 0)并缩进以下代码 - 但我觉得这很难看且不可读。

将子条件放入比赛中并不是我的选择,因为它太大了。

这在Rust中是否可行,或者是否有更好的选择(除了创建另一个子功能或其他解决方法)?

最小例子:

fn main() {
    let x = 1;

    match x {
        1 => {
            let y = 0;
            /*
             * do ev1l stuff to y that I don't want to put into the match-guard
             * as it's simply too much.
             */

            /* break early ... */
            if y == 0 {break;} // > error: `break` outside of loop [E0268]

            assert!(y != 0, "y was 0!");
            /* do other stuff in here. */
        }
        _ => {}
    }

    println!("done matching");
}

我发现这是最近的Rust blog post - 是不是错了?

  

match包含命令式和函数式编程:您可以继续使用break语句,赋值等,而不是被迫采用面向表达式的思维模式。

我还在学习Rust并且来自C所以请耐心等待我; - )

3 个答案:

答案 0 :(得分:3)

您可以创建一个像

这样的宏
macro_rules! block {
    ($xs:block) => {
        loop { let _ = $xs; break; }
    };
}

并做

match x {
    1 => block!({
        ...
        if y == 0 { break; }
        ...
    })
    _ => {}
}

这不是一个了不起的解决方案,但它具有语义意义。

答案 1 :(得分:2)

您可以将match打包成只运行一次并突破循环的loop

fn main() {
    let x = 1;

    loop { match x {
        1 => {
            let y = 0;
            /*
             * do ev1l stuff to y that I don't want to put into the match-guard
             * as it's simply too much.
             */

            /* break early ... */
            if y == 0 { break; }

            assert!(y != 0, "y was 0!");
            /* do other stuff in here. */
        }
        _ => {}
    } break; }

    println!("done matching");
}

答案 2 :(得分:2)

你可以做的其他事情是做一个自我执行的"关闭并在里面使用return语句。我不知道这是否有任何奇怪的性能特征,但在语法上它非常干净。

fn main() {
    let x = 1;

    // This closure is just used to catch the "return" statement.
    (|| {
        match x {
            1 => {
                let y = 0;
                /*
                 * do ev1l stuff to y that I don't want to put into the match-guard
                 * as it's simply too much.
                 */

                /* break early ... */
                if y == 0 { return; } // Ok!

                assert!(y != 0, "y was 0!");
                /* do other stuff in here. */
            }
            _ => {}
        }
    })();

    println!("done matching");
}

这里有playground link显示它有效。