【问题标题】:Type casting for Option typeOption 类型的类型转换
【发布时间】:2020-07-09 09:00:48
【问题描述】:

我是 Python 的 Rust 新手。我认为这是一个基本问题,但我太新了,无法通过 Type Casting Option 等关键字找到答案。

在 Python 中,为了让类型检查器知道返回类型不是 Optional[int] + int,我们可以处理 assert 逻辑来强制类型检查器知道 x 在行 assert 之后永远不会是 None

from typing import Optional


def add_one(x: Optional[int] = None) -> int:
    if x is None:
        x = 0
    assert x is not None
    return x + 1


if __name__ == '__main__':
    add_one(0)    # 1
    add_one()     # 1
    add_one(999)  # 1000

在Rust中,假设接口相同,那么如何实现相同的东西?即如何让编译器知道x的类型不再是Option

fn add_one(mut x: Option<i32>) -> i32 {
    if x == None {
        x = Some(0);
    }
    return x + 1;
}

fn main() {
    add_one(Some(0));
    add_one(None);
    add_one(Some(999));
}

这是错误信息:

error[E0369]: binary operation `+` cannot be applied to type `std::option::Option<i32>`
 --> tmp.rs:5:14
  |
5 |     return x + 1;
  |            - ^ - {integer}
  |            |
  |            std::option::Option<i32>
  |
  = note: an implementation of `std::ops::Add` might be missing for `std::option::Option<i32>`

请注意,我尝试过添加另一个类型为 i32 (let y: i32 = x;) 的变量,但对于以下消息也不起作用。

error[E0308]: mismatched types
 --> tmp.rs:5:22
  |
5 |     let y: i32 = x;
  |                  ^ expected i32, found enum `std::option::Option`
  |
  = note: expected type `i32`
             found type `std::option::Option<i32>`

【问题讨论】:

标签: rust casting type-conversion


【解决方案1】:

使用unwrap_or:

fn add_one(x: Option<i32>) -> i32 {
    x.unwrap_or(0) + 1
}

fn main() {
    assert_eq!(1, add_one(Some(0)));
    assert_eq!(1, add_one(None));
    assert_eq!(1000, add_one(Some(999)));
}

【讨论】:

    【解决方案2】:

    即如何让编译器知道 x 的类型不再是 Option 了?

    Rust 的类型检查器不必与有些狡猾的使用模式兼容,所以这样做的方法是将 x 重新定义为不再是一个选项,例如:

    fn add_one(mut x: Option<i32>) -> i32 {
        let x = if let Some(v) = x {
            v
        } else {
            0
        };
        return x + 1;
    }
    

    或者更丑、效率更低(但可能更接近 Python):

    fn add_one(mut x: Option<i32>) -> i32 {
        let x = if x == None {
            0
        } else {
            x.unwrap()
        };
        return x + 1;
    }
    

    请注意,您没有影射x,因此您也可以改为let y。这里可能会更干净。

    但正如 Boiethios 指出的那样,Rust 为这种用例提供​​了实用程序,例如unwrap_or, map_or, ...

    【讨论】:

      猜你喜欢
      • 2011-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-20
      • 2012-01-02
      • 2022-08-18
      • 2020-05-30
      • 2021-10-22
      相关资源
      最近更新 更多