访问矢量时避免可选的检查

时间:2015-05-13 17:54:43

标签: rust optional

访问Vec时如何避免可选检查?

while !self.stack.is_empty() {
    let top_path;

    if let Some(top) = self.stack.last() {
        top_path = top.to_vec();
    } else {
        panic!("error (but can't happen, becouse the stack can't be empty becouse of the while loop)");
    }

    self.stack.pop();
    self.apply_grammar(top_path);
}

有两个问题:

  1. 我必须查看if let ...声明(但我知道我不需要它)
  2. 我需要一个else panic,因为没有它top_path可能未初始化( - >错误)。
  3. 是我的错误还是Rust?

3 个答案:

答案 0 :(得分:6)

irc帮助我得到了以下答案:

while let Some(top) = self.stack.pop() {
    let top_path = top.to_vec();
    let mut is_terminal = self.tree.root.is_terminal( top.to_vec() );

    self.apply_grammar(top_path);
}

这看起来很多更好。 thx< 3

答案 1 :(得分:2)

您可以使用Option::unwrap方法,它会像None表达式一样在if let ... else上发生恐慌:

while !self.stack.is_empty() {
    let top = self.stack.last().unwrap();
    let top_path = top.to_vec();
    self.stack.pop();
    self.apply_grammar(top_path);
}

但在这种情况下,如您在自己的回答中提到的那样使用while let块会更清楚。

答案 2 :(得分:1)

在这种情况下,您应该使用迭代器。它同样有效(可能更多),而且更短:

fn main() {
    let stack = vec![1,2,3,4,5,6];

    // Consume the stack, pop from the beginning
    for i in stack {
        println!("{}", i);
    }

    let stack = vec![1,2,3,4,5,6];

    // Consume the stack, pop from the end
    for i in stack.into_iter().rev() {
        println!("{}", i);
    }

    let stack = vec![1,2,3,4,5,6];

    // Don't consume the stack, read from the beginning
    for i in &stack {
        println!("{}", i);
    }

    // Don't consume the stack, read from the end
    for i in stack.iter().rev() {
        println!("{}", i);
    }
}

在您的示例中,Rust不知道is_emptypop之间存在任何关联,因此它必须处理pop中的失败案例。迭代器为向量公开了一个更加知识化的接口,并且可以避免检查越界以进行引导。