【问题标题】:Understanding Rust's function return type理解 Rust 的函数返回类型
【发布时间】:2019-11-29 01:40:42
【问题描述】:

我试图通过从书中学习 Rust 来学习它。最常见的东西,上面有有趣的补充。我尝试编写一些代码来适应它,所以我决定按照本章所述做,并编写一个快速的斐波那契函数,但出现了一个错误,我遇到了问题。任何防锈专家都会向我解释为什么会发生这种情况及其背后的逻辑。

fn fibo(x: i32) -> i32 {
    if x == 0 {
        0
    }
    else if x == 1 {
        1
    }

    fibo(x-1) + fibo(x-2)    
}

当我尝试构建此代码时,我收到以下错误;

error[E0308]: mismatched types
 --> src/main.rs:6:9
  |
6 |         0
  |         ^ expected (), found integer
  |
  = note: expected type `()`
             found type `{integer}`

error[E0308]: mismatched types
 --> src/main.rs:9:9
  |
9 |         1
  |         ^ expected (), found integer
  |
  = note: expected type `()`
             found type `{integer}`

但如果我将代码更改为以下代码,它就可以正常工作;

fn fibo(x: i32) -> i32 {
    if x == 0 {
        0
    }
    else if x == 1 {
        1
    }else{
        fibo(x-1) + fibo(x-2)    
    }
}

Rust Language 书中指出,编译器会检查 if-else 块中所有表达式的类型,但如果不存在 else 语句,则它会传递到下一行代码。既然我说返回类型是 i32,编译器怎么会期望错误中看到的类型“()”?

【问题讨论】:

  • 顺便说一句,在 rust 中,尝试使用 match 而不是 if..else if.
  • @sailfish009 的确,它更强大,但是,在这里他的结果有限,所以match 可能是矫枉过正

标签: function rust return-type


【解决方案1】:

这里的问题是你试图有两个“return”语句。

当块的最后一条语句缺少分号时,语句的结果是评估整个块的类型。在伪锈中,我们可以这样说

{
    0
} -> usize

也就是说

let x = { 0 };

0 创建一个新范围,隐式返回它,因为块中没有分号,然后它就变成了块的类型。所以,x: usize

那么,发生了什么?
您的代码有 两个 隐式返回:

fn fibo(x: i32) -> i32 {
    if x == 0 { // This starts a block
        0 // First implicit return
    }
    else if x == 1 { // This also starts a block
        1 // First implicit return
    } // Therefore this entire if/else statement is an implicit return unless its output
      // is suppressed with a semicolon.

    fibo(x-1) + fibo(x-2) // Here we try to return again, which confuses rust!
} 

因为您的if/else 包含隐式返回并且没有分配给变量,所以就像我说的如下:

fn fibo(x: i32) -> i32 {
    //For the sake of explanation, let's assume x == 0
    0 // instead of your if/else

    fibo(x-1) + fibo(x-2)
}

哦不!如何解决这个问题:

fn fibo(x: i32) -> i32 {
    if x == 0 {
        // return 0; // This is an early return; this will break until it reaches the function
        0 // Since this is about implicit returns I'll use them here
    } else if x == 1 {
        1
    } else {
        fibo(x - 1) + fibo(x - 2)
    }
}

【讨论】:

  • 有趣的是:这些并不完全是返回,而是语句的结果。虽然它通常是相似的,因为 rust 函数本身就是语句,它不会转化为与其他语言相同的行为,即返回第一个结果。
【解决方案2】:

您正试图从以() 作为返回的 if-else 块返回。您可以明确指定返回值,即:

fn fibo(x: i32) -> i32 {
    if x == 0 {
        return 0;
    }
    else if x == 1 {
        return 1;
    }

    fibo(x-1) + fibo(x-2)    
}

编辑: 提高清晰度,你所做的是你试图从一个不能取任何值的 if-else 块返回,所以如果你必须返回函数,您必须明确声明 return 0; 或其他任何内容。 编辑:在这里,您的代码不起作用,因为您的 if-else 块不是函数中的最后一件事。 例如,这将完美无缺:

fn some_func(val: u8) -> u8 {
    if val == 100 {
       0
    }
    else {
        1
    }
}

【讨论】:

  • 我认为这个答案没有清楚地描述问题/解决方案 - 是不是因为“if else set”不是函数中的最后一件事?
  • @LukeJoshuaPark 他正试图从 if-else 块返回。是的,你是对的,我已经更新了我的答案
猜你喜欢
  • 2019-07-30
  • 2021-02-01
  • 1970-01-01
  • 2021-03-30
  • 2018-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多