有些和无,它们是什么?

Syn*_*ose 38 rust

在编写一些试图习惯Rust的小型初级练习时,我遇到了一些我不懂的输出Vec::get.这是代码:

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

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

输出是

0 Some(('G', 'H'))
1 Some(('H', '5'))
2 None
Run Code Online (Sandbox Code Playgroud)

我在Haskell涉足面前,我的意思是看了教程网站10分钟,跑回C++,但我记得读的东西SomeNoneHaskell的.我很惊讶在Rust看到这个.有人可以解释为什么.get()返回SomeNone

huo*_*uon 34

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

fn get(&self, index: usize) -> Option<&T>
Run Code Online (Sandbox Code Playgroud)

也就是说,它返回一个Option,这是一个定义为的枚举

pub enum Option<T> {
    None,
    Some(T),
}
Run Code Online (Sandbox Code Playgroud)

None并且Some是枚举的变体,也就是说,类型的值Option<T>可以是a None,也可以是Some包含type的值T.

这与data Maybe a = Nothing | Just aHaskell中的核心类型相同; 两者都代表一个可选值,它可以是(Some/ Just),也可以不是(None/ Nothing).

当只有一种可能导致失败的原因时,这些类型通常用于表示失败,例如,.get用于Option给出类型安全的边界检查数组访问:None当索引超出界限时它返回(即没有数据),否则它返回Some包含请求指针的a.


Joh*_*sen 7

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

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

  • *Rust 语言不支持(不安全的)NULL 指针*——这 [不完全正确](http://doc.rust-lang.org/std/ptr/fn.null.html),但是你的回答的精神是正确的。 (3认同)

Vla*_*eev 6

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

返回给定索引处的切片元素,或者None索引是否超出范围.

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

还有另一种方法可以访问切片中的元素 - 索引操作符,您应该熟悉它:

let nums = [1, 2, 3];
let x = nums[1];
Run Code Online (Sandbox Code Playgroud)

它直接返回切片的元素,但如果索引超出范围,它将失败当前任务:

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

该程序失败:

% ./main2
1
2
task '<main>' failed at 'index out of bounds: the len is 2 but the index is 2', main2.rs:4
Run Code Online (Sandbox Code Playgroud)

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

如果你不知道什么SomeNone真的是,为什么他们都需要在一般情况下,你应该阅读官方 教程,它解释了它,因为它是很基本的概念.


Yil*_*maz 5

选项枚举有 2 个变体。

1-None用于表示失败或无值

2-Some这是包装值的元组结构

如果你需要在 OOB 中编写这个结构,例如在 中typescript,你会这样写。这将使情况更容易可视化

  • 将 Option 接口定义为派生类

    interface Option<T = any> {
      // pass all the methods here 
      // unwrap is used to access the wrapped value
      unwrap(): T;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 编写Some继承自的类Option

Some类返回一个值

class Some<T> implements Option<T> {
  private value: T;
 
  constructor(v: T) {
    this.value = v;
  }
 
  unwrap(): T {
    return this.value
}}
Run Code Online (Sandbox Code Playgroud)
  • 编写None也继承自的类Option

None类返回 null

class None<T> implements Option<T> {
 // you do not need constructor here     
  unwrap(): T {
    return null as T;
  }
}
Run Code Online (Sandbox Code Playgroud)