Can& some(_)in vec.iter(){..}编译?

时间:2014-05-24 01:12:44

标签: rust

我尝试运行以下代码段:

let a = &[Some(1), Some(2), Some(3), None, Some(4)];

let mut sum = 0;
for &Some(x) in a.iter() {
    sum += x;
}

assert_eq!(sum, 1+2+3+4);

编译器回复:

about_loops.rs:39:9: 43:18 error: non-exhaustive patterns: None not covered
about_loops.rs:39         for &Some(x) in a.iter() {
about_loops.rs:40             sum += x;
about_loops.rs:41         } 
about_loops.rs:42 
about_loops.rs:43         assert_eq!(sum, 1+2+3+4);
error: aborting due to previous error
make: *** [all] Error 101

我是否可以在不使用luke和hobbs建议的匹配表达式的情况下为for循环编译这样的构造?或者此错误消息是误导性的? 鉴于for的语法定义,似乎没有这样做。

for_expr : "for" pat "in" expr '{' block '}' ;

我在:

rustc 0.11.0-pre-nightly (6291955 2014-05-19 23:41:20 -0700)
host: x86_64-apple-darwin

澄清:“表达式”是多么具有表现力。 for_expr的一部分?与http://doc.rust-lang.org/rust.html#for-expressions下的定义相比,未在http://doc.rust-lang.org/rust.html#match-expressions下指定。

5 个答案:

答案 0 :(得分:3)

for循环的模式基本上与let具有相同的限制:它必须是无可辩驳的,也就是说,它不能无法匹配。

无可辩驳的模式的示例是&,元组,结构和单变量枚举。其他模式(如多变量枚举或文字)不能保证始终匹配,因为该类型允许模式未涵盖的值。

for构造本质上是一个消解如下的宏(它在扩展宏的同一遍中去掉,你可以看到它用--pretty expanded手动运行rustc):

for <pattern> in <iter_expression> {
    <code>
}

// becomes

match &mut <iter_expression> { // match to guarantee data lives long enough
    it => {
        loop {
            match it.next() {
                None => break,
                Some(<pattern>) => { <code> }
            }
        }
    }
}

这是正常的match,即武器必须是详尽的(涵盖所有可能性),因此如果<pattern>只是&Some(_),那么Some(&None)可能性不包括在内。

Some部分基本上等同于Some(value) => { let <pattern> = value; ...。现在考虑一下,这可能实际上是一个可以提供更好错误信息的desugaring:我提交了#14390。)

答案 1 :(得分:1)

Some是枚举中的一种类型。 Option枚举有两种类型,Some(T)None。您的代码假定a.iter()始终为Some(T),并且从不检查None。要添加支票,您可以使用match。像这样:

let a = &[Some(1), Some(2), Some(3), None, Some(4)];

let mut sum = 0;
for &j in a.iter() {
  match j {
    Some(x) => sum += x,
    None => ()
  }
}

assert_eq!(sum, 1+2+3+4);

希望有所帮助!

答案 2 :(得分:1)

fora中的每个元素绑定到模式&Some(x) - 所以当a的第一个元素是&Some(1)时,x变为1.但None与模式&Some(x)不匹配,因此绑定无法成功。 Rust根据a的类型实际为Option(包含Some(_)None的类型)的字面值推断,并且您的模式不会覆盖所有的可能性。而不是等待运行时告诉你它不知道该怎么做,而是在编译时抛出错误。

从我所知道的小Rust(大部分已阅读教程)中我认为你需要做类似的事情:

for &thing in a.iter() {
    match thing {
        Some(x) => sum += x
        None => /* do nothing */
    }
}

答案 3 :(得分:1)

以下也有效:

use std::iter::AdditiveIterator;

fn main() {

    let a = &[Some(1), Some(2), Some(3), None, Some(4)];
    let sum = a.iter().filter_map(|x| *x).sum();
    assert_eq!(sum, 1+2+3+4);
}

答案 4 :(得分:1)

这也有效:

let sum = a.iter().fold(0, |s, e| s + e.unwrap_or(0));