【问题标题】:What are Some and None?什么是一些和无?
【发布时间】:2021-09-10 12:57:53
【问题描述】:

我遇到了一些使用Vec::get 无法理解的输出。代码如下:

fn main() {
    let command = [('G', 'H'), ('H', '5')];

    for i in 0..3 {
        print!(" {} ", i);
        println!("{:?}", command.get(i));
    }
}

输出是

 0 Some(('G', 'H'))
 1 Some(('H', '5'))
 2 None

我以前涉足过 Haskell,我的意思是看了一个教程网站 10 分钟然后跑回 C++,但我记得读过一些关于 Haskell 的 SomeNone 的内容。我很惊讶在 Rust 中看到这一点。有人可以解释为什么.get() 返回SomeNone

【问题讨论】:

    标签: rust optional


    【解决方案1】:

    get 的签名(对于切片,不是 Vec,因为您使用的是数组/切片)是

    fn get(&self, index: usize) -> Option<&T>
    

    也就是说,它返回一个Option,它是一个枚举,定义如下

    pub enum Option<T> {
        None,
        Some(T),
    }
    

    NoneSome 是枚举的变体,即Option&lt;T&gt; 类型的值可以是None,也可以是Some包含T 类型的值。您也可以使用变体创建 Option 枚举:

    let foo = Some(42);
    let bar = None;
    

    这与Haskell中的核心data Maybe a = Nothing | Just a类型相同;两者都代表一个可选值,它要么存在(Some/Just),要么不存在(None/Nothing)。

    当某些事情失败的原因只有一种可能性时,这些类型通常用于表示失败,例如,.get 使用 Option 提供类型安全的边界检查数组访问:它返回 None(即没有data) 时索引超出范围,否则返回包含请求指针的Some

    另见:

    【讨论】:

      【解决方案2】:

      SomeNone 视为解决Rust 语言不支持“安全”使用NULL 指针这一事实的规范“安全”方式。由于您的Vec 的长度为3,并且您只指定了两对,因此第三对实际上是NULL;它不是返回NULL,而是返回None

      Rust 通过在编译时通过Some / None 强制我们始终处理None 被返回的可能性来提供安全保证。

      【讨论】:

      • Rust 语言不支持(不安全的)NULL 指针 — 那是 not completely true,但您的回答精神是正确的。
      • 谢谢;我可以看到它们对于与 C 交互是必需的。
      • 不仅如此,还适用于您需要不安全的时候。数据结构通常会在内部使用原始指针。
      • 另一个好点。我已编辑我的答案以使其更准确。
      【解决方案3】:

      command 不是向量(类型为Vec&lt;T&gt;),它是一个固定大小的数组(类型为[(char, char); 2] 在您的情况下),并且数组会自动借入切片(视图到数组中),因此您可以使用切片上定义的所有方法,包括get:

      返回给定索引处的切片元素,如果索引超出范围,则返回None

      行为非常明显:当给定索引有效时,它返回 Some 以及该索引下的元素,否则返回 None

      还有另一种访问切片中元素的方法——索引操作符,你应该很熟悉:

      let nums = [1, 2, 3];
      let x = nums[1];
      

      直接返回分片的元素,但是如果索引越界,会导致当前任务失败:

      fn main() {
          let x = [1, 2];
          for i in 0..3 {
              println!("{}", x[i]);
          }
      }
      

      这个程序失败了:

      % ./main2
      1
      2
      task '<main>' failed at 'index out of bounds: the len is 2 but the index is 2', main2.rs:4
      

      为了方便需要get()方法;如果给定的索引是有效的,它可以避免你提前检查。

      如果您不知道 SomeNone 到底是什么以及为什么需要它们,您应该阅读 official tutorial,它解释了它,因为它是非常基本的概念。

      【讨论】:

        【解决方案4】:

        讨论 get() 的返回类型为 option enum 的其他答案是准确的,但我认为有用的是如何从打印中删除一些。要做到这一点,一种快速的方法是只调用选项的 unwrap,尽管这不是生产推荐的。有关选项的讨论,请查看 rust book here

        Updated with unwrap code in playground (below)

        fn main() {
            let command = [('G', 'H'), ('H', '5')];
        
            for i in 0..3 {
                print!(" {} ", i);
                println!("{:?}", command.get(i).unwrap());
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2014-06-22
          • 1970-01-01
          • 1970-01-01
          • 2019-11-08
          • 1970-01-01
          • 1970-01-01
          • 2011-03-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多