我是Rust的新手,我试图用循环写一个简单的例子,代码如下:
fn main() {
let exit: u8 = loop_break(20, 5);
println!("loop_break exited with value {exit}");
let exit: u8 = loop_break(20, 35);
println!("loop_break exited with value {exit}");
let exit: u8 = loop_break(20, 20);
println!("loop_break exited with value {exit}");
}
fn loop_break(cycles: u8, exit: u8) -> u8 {
if exit > cycles {
cycles
}
let mut _i:u8 = 0;
loop {
if _i == exit {
break exit - 1;
}
_i += 1;
}
return _i;
}
当我试着编译它的时候编译器给我这个我能理解的错误信息
error[E0308]: mismatched types
--> src/main.rs:23:9
|
22 | / if exit > cycles {
23 | | cycles
| | ^^^^^^ expected `()`, found `u8`
24 | | }
| |_____- expected this to be `()`
|
help: you might have meant to return this value
|
23 | return cycles;
| ++++++ +
error[E0308]: mismatched types
--> src/main.rs:29:19
|
29 | break exit - 1;
| ^^^^^^^^ expected `()`, found `u8`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `flow-control` due to 2 previous errors
如果我将函数定义为返回u8类型,为什么编译器声明它需要一个单位值?
2条答案
按热度按时间jm81lzqq1#
Rusts希望您的第一个
if
语句返回单位类型,因为它没有else
分支。条件语句(如if
或match
)的所有分支/分支必须返回相同的类型,并且如果它们应该返回单位类型以外的内容,则必须是完整的。任何情况都不能被忽略。如果您省略else
,你不处理所有if
的条件是false
的情况。因此,编译器会自动假设你不完整的条件语句必须返回单元类型,这是Rust中的一种特殊类型,表示“没有返回任何东西”。把你不完整的if
语句当作语法糖:cycles
是u8
,()
是()
类型,它们不是同一类型,本书的这一部分可能会引起你的兴趣。这里你想做的是编译器建议的。你想提前从函数返回,使用
return
语句:在本书的这一节中阅读更多关于表达式(
cycles
)和语句(return cyclces;
)之间的区别。关于
break
的错误,如果你想用break
返回一个来自loop
的值,Rust要求你使用返回的值。你必须将它绑定到一个变量:将其从表达式转换为带有尾随分号的语句:
或者将其作为函数的最后一个表达式(因为最后一个表达式会自动从函数返回)。这需要在循环后删除
return _i;
。luaexgnf2#
在Rust中,许多语句可以被认为是表达式,然后提供一个值。例如,
if cond { statement_1 } else { statement_2 }
可以这样使用:let result = if cond { statement_1 } else { statement_2 };
。这意味着这个替代方案的两个语句必须具有相同的类型,以便存储在结果变量中。回到您的代码,您的第一个
if
语句没有else
分支;这类似于else
分支包含()
(在Rust中称为unit
,类似于其他语言中的void
)。因此,if
的第一个分支也必须提供()
;但是它提供了cycles
(一个u8
),因此报告了错误。如果你想放弃一个表达式的结果,而计算为()
,你需要添加一个分号。但是在你的例子中,这会使if
语句变得无用。也许你想要return cycles;
(编译器建议的)为了直接离开函数,返回cycles
作为结果。如果
break
与表达式一起使用,这意味着我们要将整个循环视为一个表达式。(let result = loop { ... };
)。这里不是这种情况,因此不应提供具有break
的表达式,因为它会被丢弃。也许你会使用return exit - 1;
代替?在这种情况下,离开循环将离开函数,最后一条语句return _i;
变得不可访问。顺便说一下,如果我们用一个简单的break;
离开循环,则将到达最后的return _i;
语句,并且由于它是函数的最后一个语句,所以它可以被简化为_i
(没有return
,没有分号),因为它的求值被认为具有整个块的值,即函数体,因此是函数的结果。