Rust中的简单程序有编译错误

gstyhher  于 2023-03-23  发布在  其他
关注(0)|答案(2)|浏览(124)

我是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类型,为什么编译器声明它需要一个单位值?

jm81lzqq

jm81lzqq1#

if exit > cycles {
    cycles
}

Rusts希望您的第一个if语句返回单位类型,因为它没有else分支。条件语句(如ifmatch)的所有分支/分支必须返回相同的类型,并且如果它们应该返回单位类型以外的内容,则必须是完整的。任何情况都不能被忽略。如果您省略else,你不处理所有if的条件是false的情况。因此,编译器会自动假设你不完整的条件语句必须返回单元类型,这是Rust中的一种特殊类型,表示“没有返回任何东西”。把你不完整的if语句当作语法糖:

if exit > cycles {
    cycles
} else {
    ()
}

cyclesu8()()类型,它们不是同一类型,本书的这一部分可能会引起你的兴趣。
这里你想做的是编译器建议的。你想提前从函数返回,使用return语句:

if exit > cycles {
    return cycles;
}

在本书的这一节中阅读更多关于表达式(cycles)和语句(return cyclces;)之间的区别。
关于break的错误,如果你想用break返回一个来自loop的值,Rust要求你使用返回的值。你必须将它绑定到一个变量:

let _ = loop {
    if _i == exit {
        break exit - 1;
    }
    _i += 1;
};

将其从表达式转换为带有尾随分号的语句:

loop {
    if _i == exit {
        break exit - 1;
    }
    _i += 1;
};

或者将其作为函数的最后一个表达式(因为最后一个表达式会自动从函数返回)。这需要在循环后删除return _i;

luaexgnf

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,没有分号),因为它的求值被认为具有整个块的值,即函数体,因此是函数的结果。

相关问题