Why does removing return give me an error: expecte

2020-01-27 05:56发布

I'm writing an is_prime function in Rust, and I was under the impression that simply writing true was the equivalent of return true;, but this is not the case in my function:

fn is_prime(number: i64) -> bool {
    for i in 2i64..number {
        if number % i == 0 && i != number {
            false
        }
    }
    true
}

This will give me the error:

error[E0308]: mismatched types
 --> src/lib.rs:4:13
  |
4 |             false
  |             ^^^^^ expected (), found bool
  |
  = note: expected type `()`
             found type `bool`

Replacing true and false with return true; / return false; works, but why does using the previous not compile?

标签: rust
1条回答
太酷不给撩
2楼-- · 2020-01-27 06:20

Rust is expression-oriented. In any block, the last expression inside it is the value of the block. Thus, for a function, the last value in the block is treated as a return value.

In other blocks, though, this is not the case—the last value is, after all, treated as the value of the block, not as a return value for the function.

Take the snippet in isolation with just a bit added for clarity:

let has_factor = if number % i == 0 && i != number {
    false
}

This means that the outcome of the if statement as a whole is false if the clause is true, and that value is then duly inserted into the has_factor variable. If the clause is not true, then the else clause will be evaluated. Given that there is no else clause, it is as though else { } had been written, which is equivalent to else { () }. This else block evaluates to (), the unit type. Now we have a mismatch: is the if block (and hence the has_factor variable) of the type bool, as the if block requires, or (), as the [lack of] else block requires? This is where the error comes from.

Summary: you can’t just omit the return keyword, because that’s not what the expression orientation means. At the end of a function, they boil down to the same thing and the sans-return form should be preferred, but in other locations they are not equivalent and return must be explicit.

Final code:

fn is_prime(number: i64) -> bool {
    for i in 2..number {
        if number % i == 0 && i != number {
            return false;
        }
    }
    true
}
查看更多
登录 后发表回答