如何跳出 Rust 中的 do-while 风格循环?

ide*_*n42 3 rust

Rust 允许一种 do-while 循环,例如:

所以C风格:

do {
    something();
} while (test());
Run Code Online (Sandbox Code Playgroud)

可以用 Rust 写成:

while {
    something();
    test()
}{}
Run Code Online (Sandbox Code Playgroud)

但是在这种情况下使用 break 会出现问题:

所以这个C风格:

do {
    if (something()) {
        break;
    }
} while (test());
Run Code Online (Sandbox Code Playgroud)

不能用 Rust 写成:

while {
    if (something()) {
        break;
    }
    test()
}{}
Run Code Online (Sandbox Code Playgroud)

编译失败cannot break outside of a loop

有没有办法摆脱这种形式的while循环?


注 1)使用的原因:在这种情况下将在最初进入循环时使用
do {...} while test()流控制而不是。
while test() {...}test()false

注2)使用 while {...}流程控制时:continue在代码体中调用将跳过最后的break检查。

请参阅相关问题:如何在宏中包装 do-while 样式循环,保持“继续”流程控制?

use*_*342 5

正如评论中提到的,了解这种模式的工作原理很重要。它不是 的特殊形式while,它只是滥用循环测试来做通常在体内完成的事情。由于breakcontinue不属于循环测试(除非循环是另一个循环的一部分,在这种情况下它们将编译,但中断/继续外部循环),Rust 拒绝它们。

模拟break上述模式的一种直接方法是将测试代码移动到一个可以退出的闭包中return

while (|| {
    if something() {
        return false // break
    }
    test()
})() {}
Run Code Online (Sandbox Code Playgroud)

continue可以以相同的方式模拟,只需true从闭包中返回即可。

如果将其表示为宏,则可能会使意图更清晰。


小智 1

接近您的主张的有效解决方案可能是:

while {
    // bloc
    test()
} {
    // break conditions belonging here
    if (something()) {
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

一些备注:

  • 第一个括号必须是一个表达式,Rust 允许用户在它之前编写语句,整个blocwithtest()被视为一个表达式,但正如您所指出的,存在一些限制
  • 构建良好的循环通常会避免 break 和 continue 语句,该解决方案的优点是将第一个括号中的循环流逻辑与第二个括号中异常使用的添加控制逻辑分开,因为它是循环外部的参数
  • 这次在test()之后调用something(),这意味着它将无法打破循环的第一次迭代