Avoid additional validation when accessing the vector

How can I avoid additional validation when accessing 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);
}

      

There are 2 problems:

  • I need to check with the operator if let

    ... (but I know I don't need this)
  • I need else panic

    it because without it it top_path

    can be uninitialized (-> error).

Is it my fault or is it Rusta?

+3


source to share


3 answers


irc helped me with the following answer:

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);
}

      



and it looks much nicer. thanks <3

+6


source


You can use a method Option::unwrap

that panics in the None

same way as an expression 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);
}

      



but in this case it would be even clearer to use a block while let

as you mentioned in your own answer.

+2


source


In this case, you must use an iterator. It's just as efficient (maybe more) and shorter:

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);
    }
}

      

In your example, Rust does not know that there is a relationship between is_empty

and pop

, so it must handle the failure case in pop

. The iterator provides a more recognizable interface to the vector and may not check for load outside of the bounds.

+1


source







All Articles