返回表达式 return
return
表达式用于函数或者闭包 (closure)中, 从当前函数上下文退出, 返回到函数调用处.
如果函数的返回值为空, 它返回的是 ()
, 即所谓的 unit struct
, 类似于 C 语言中的 void
. 比如:
fn do_some() -> () {
...
return;
}
类似于:
void do_some() {
...
return;
}
如果 return obj;
表达式是函数中最后一个表达式, 那么 return
表达式中可以简写为 foo
, 看个例子:
#![allow(unused)] fn main() { fn max_num(a: i32, b: i32) -> i32 { if a > b { return a; } else { return b; } } }
通常会被简写成以下形式:
#![allow(unused)] fn main() { fn max_num(a: i32, b: i32) -> i32 { if a > b { a } else { b } } }
return 表达式的优先级
先看一个基于 RustQuiz#20 修改的示例程序, 考虑考虑程序运行的结果是什么样的:
#![allow(unreachable_code)] #![allow(unused_braces)] #[rustfmt::skip] fn return1() { if (return { println!("1") } ) { } } #[rustfmt::skip] fn return1_expanded() { if (return println!("1")) { } } fn return1_simplified() { println!("1") } #[rustfmt::skip] fn return2() { if return { println!("2") } { } } #[rustfmt::skip] fn return2_expanded() { if return println!("2") { } } fn return3() { if (return { println!("3"); }) {} } fn main() { return1(); return1_expanded(); return1_simplified(); return2(); return2_expanded(); return3(); }
其中, return1()
函数的 MIR 代码如下:
fn return1() -> () {
let mut _0: ();
let _1: ();
let mut _2: std::fmt::Arguments<'_>;
let mut _3: &[&str];
let mut _4: &[&str; 1];
bb0: {
_4 = const return1::promoted[0];
_3 = _4 as &[&str] (PointerCoercion(Unsize));
_2 = Arguments::<'_>::new_const(move _3) -> [return: bb1, unwind continue];
}
bb1: {
_1 = _print(move _2) -> [return: bb2, unwind continue];
}
bb2: {
return;
}
}
const return1::promoted[0]: &[&str; 1] = {
let mut _0: &[&str; 1];
let mut _1: [&str; 1];
bb0: {
_1 = [const "1\n"];
_0 = &_1;
return;
}
}
再看一下 return2()
函数的 MIR 代码:
fn return2() -> () {
let mut _0: ();
let _1: ();
let mut _2: std::fmt::Arguments<'_>;
let mut _3: &[&str];
let mut _4: &[&str; 1];
bb0: {
_4 = const return2::promoted[0];
_3 = _4 as &[&str] (PointerCoercion(Unsize));
_2 = Arguments::<'_>::new_const(move _3) -> [return: bb1, unwind continue];
}
bb1: {
_1 = _print(move _2) -> [return: bb2, unwind continue];
}
bb2: {
return;
}
}
const return2::promoted[0]: &[&str; 1] = {
let mut _0: &[&str; 1];
let mut _1: [&str; 1];
bb0: {
_1 = [const "2\n"];
_0 = &_1;
return;
}
}
对比 return2()
的 MIR 代码可以发现, 它与 return1()
的代码是相同的.
从这里我们可以学习到, return
表达式比 if
表达式有更高的优先级, 它优先与后面的表达式结合, 组合成 return
表达式,
并作为 if
表达式的条件 (condition).
如何理解呢? return
有更高的优先级, 它优先与大括号中的语句结合, 所以那个大括号是多余的,
cargo clippy
会给出相应的提示, 就像下图所示: