Rust的比赛早破

lar*_*key 5 pattern-matching break match rust

我想针对许多可能的情况进行切换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");
}
Run Code Online (Sandbox Code Playgroud)

我发现了这则最近的Rust博客文章 -是吗?

match包含命令式和函数式两种编程风格:您可以继续使用break语句,赋值等,而不必强迫他们采用面向表达式的思维方式。

我仍在学习Rust,并且来自C语言,所以请多多包涵;-)

小智 13

这在某些时候发生了变化,现在您可以使用标签来打破任何块!

例如

fn main() {
    let x = 1;

    match x {
        1 => 'label: {
            let y = 0;

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

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

    println!("done matching");
}
Run Code Online (Sandbox Code Playgroud)


oli*_*obk 7

您可以将 包装matchloop只运行一次并跳出循环的

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");
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个有趣的方法,但我认为它混淆了这个想法而不是它应该的,并且不完全是我问题的答案。有一个upvote,但我不能接受它;) (7认同)
  • 为什么它没有回答你的问题?它可以让你退出比赛,对吗?我问这个问题是因为我正在移植一个大的 C 1000+ 行 switch 语句,这几乎就是我处理比赛中途突破的方式 (2认同)

Vee*_*rac 6

你可以创建一个宏

macro_rules! block {
    ($xs:block) => {
        loop { let _ = $xs; break; }
    };
}
Run Code Online (Sandbox Code Playgroud)

并做

match x {
    1 => block!({
        ...
        if y == 0 { break; }
        ...
    })
    _ => {}
}
Run Code Online (Sandbox Code Playgroud)

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


小智 6

您可以做的其他事情是创建一个“自执行”闭包并在其中使用 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");
}
Run Code Online (Sandbox Code Playgroud)

这是一个显示它工作的游乐场链接

  • *任何奇怪的性能特征*——不应该像我期望的那样被 Rust 的“零成本抽象”覆盖。 (2认同)