rust if 语句提前返回

假设有如下代码,max是一个求最大值的函数,这在其他语言中很常见,但在rust中却无法通过编译

1
2
3
4
5
6
7
8
9
10
11
12
pub fn max(a: i32, b: i32) -> i32 {
if a > b {
a
}
b
}

fn main() {
let v = max(1, 11);
println!("max {}", v);
}

报错如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
error[E0308]: mismatched types
--> examples/main5.rs:3:9
|
2 | / if a > b {
3 | | a
| | ^ expected `()`, found `i32`
4 | | }
| |_____- expected this to be `()`
|
help: you might have meant to return this value
|
3 | return a;
| ^^^^^^ ^

其原因是上述写法在判断了a > b成立后并不会隐式返回(implicit returns) 而是会继续往下执行,这样就出现了一个表达式中重复return的情况,这是不被编译器允许的

对于语句 (statement) 来说,它接收一个表达式,丢弃表达式的值并返回 () , 在The Rust Programming Language中这么描述两者的区别

Statements are instructions that perform some action and do not return a value. Expressions evaluate to a resulting value

尝试在if 表达式后加上 ; ,将其转化为一个语句 (statement)

1
2
3
4
5
6
pub fn max(a: i32, b: i32) -> i32 {
if a > b {
a
};
b
}

依然会报错

1
2
3
4
5
6
7
8
9
10
11
error[E0317]: `if` may be missing an `else` clause
--> examples/main5.rs:2:5
|
2 | / if a > b {
3 | | a
| | - found here
4 | | };
| |_____^ expected `()`, found `i32`
|
= note: `if` expressions without `else` evaluate to `()`
= help: consider adding an `else` block that evaluates to the expected type

但原因和之前不一样,这次是由于 if 是一个表达式,因此有返回值。两个分支的返回值类型必须匹配。如果没有else分支,那不存在的else分支的返回值将是(),它与 if 分支的返回类型 i32不匹配

一种解决方式是给函数添加else分支

1
2
3
4
5
6
7
pub fn max(a: i32, b: i32) -> i32 {
if a > b {
a
} else {
b
}
}

另一种方式最开始的报错已有提示 help: you might have meant to return this value return a;

1
2
3
4
5
6
pub fn max(a: i32, b: i32) -> i32 {
if a > b {
return a;
}
b
}

使用return关键字显式返回 (explicitly returns) 也能实现需求