实施例1
fn five() -> i32 {
5 // ; not allowed I understand why
}
fn main() {
let x = five();
println!("The value of x is: {x}");
}
Run Code Online (Sandbox Code Playgroud)
示例 2(来自https://doc.rust-lang.org/stable/book/ch03-05-control-flow.html)
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("The result is {result}");
}
Run Code Online (Sandbox Code Playgroud)
我明白为什么在示例 1 中它必须是5而不是5;,但我对示例 2 感到困惑,并且有几个问题。
为什么我们这里有;?没有它也能工作;,那么为什么它在那里呢?这是一些 Rust 约定还是有一些技术原因?
如果我这样做,break; counter * 2;它不会返回值。break; counter * 2;和 和有什么区别break counter * 2;?
为什么第二个有效?
如果我做:
break counter * 2
println!("After break");
Run Code Online (Sandbox Code Playgroud)
编译错误是:错误:预期;,发现println
如果我这样做:
break counter * 2;
println!("After break");
Run Code Online (Sandbox Code Playgroud)
不再有编译错误,但是:
15 | println!("After break");
| ^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement
Run Code Online (Sandbox Code Playgroud)
但至少我明白这一点。
我不明白的是为什么它 break counter * 2工作正常,但如果我在它后面添加一些东西,我们就会出现编译错误。
老实说,我对示例 2 感到困惑,我的理解是,如果我们想从表达式返回值,最后一行应该没有“;” (如示例 1),但示例 2 显然证明了事实并非如此。
Sil*_*olo 19
Rust 是一种非常面向表达的语言。至关重要的是,表达式返回值。当你编写一个函数时,你就是在编写一个表达式。该表达式可以由多个用分号分隔的语句组成。
这就是 Rust 与大多数其他 C 派生语言的不同之处。表达式是 Rust 中的驱动程序,分号分隔语句。所以一个有效的表达式是{ a ; b ; c ; d },其中d是最终结果。a、b、 和c只是副作用。相比之下,在 C 中,函数是由分号终止的语句序列,并且语句包含表达式。因此,在 C 中,函数体可能看起来像{ a ; b ; c ; d ; },其中执行每个语句都是为了产生副作用,其中一个可能碰巧是一个return语句,但它仍然是一个语句。
如果 Rust 中的表达式序列以分号结尾,Rust 会假设您打算插入一个额外的字符()作为结尾,因此{ a ; b ; c ; d ; }会转换为{ a ; b ; c ; d ; () }. 这就是为什么我们不必()在所有返回单元的函数的末尾编写。这只是默认值。
这是一种更实用的看待事物的方式。函数返回一个值,无论发生什么都是副作用。函数末尾的“通常”返回值就是该值,作为表达式。
现在,因为 Rust 支持更命令式的风格(并且因为它通常有用且方便),Rust 还支持诸如breakand之类的语句return,这些语句早期就打破了通常的控制流。这些是陈述。它们对返回值有副作用,但它们不是表达式的“通常”返回值。
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
Run Code Online (Sandbox Code Playgroud)
loop像 Rust 中的大多数东西一样,的内部是一个表达式。所以它可以返回一个值。该值将被忽略,因为循环将再次运行。在这种情况下,该块相当于
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
()
} else {
() // 'if' can also insert () in the else block when used as an expression
}
};
Run Code Online (Sandbox Code Playgroud)
我们()明确返回。如果删除分号,您将得到
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2
} else {
() // 'if' can also insert () in the else block when used as an expression
}
};
Run Code Online (Sandbox Code Playgroud)
break作为表达式,也“返回”一个值。该值属于发散类型,称为neveror!。由于break保证会发散(即退出通常的控制流),因此它返回!,这是Rust 中唯一与所有其他类型兼容的类型。所以这个表达式的结果if仍然是(),因为!可以转换为()。当然,这都是没有意义的,因为loop如果没有被破坏,它将再次运行,但这就是 Rust 内部的推理。
总之,您不会尝试从{ ... }循环块的最后一行返回。你试图跳出循环,这不是正常的返回;它打破了循环遵循的通常规则,因此它需要一个特殊的语句,并且Rust 中的语句之间用分号分隔。事实上,您可以在没有分号的情况下结束语句序列,这是偶然的,因为loop无论如何都会忽略其块的结果。
| 归档时间: |
|
| 查看次数: |
4098 次 |
| 最近记录: |