Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Get first and all of an iterator. In Rust

What I am trying to do

I have in iterator returned from std::str::SplitWhitespace, I need the first element, and a vector of all elements.

What I have tried

I tried to use peek. However this seems to need a mutable (I can’t we why), and I end up with borrowing errors.

Simplified code, with compile errors.

fn main(){
    let line = "hello, world";
    let mut tokens = line.split_whitespace().peekable();
    if let Some(first) = tokens.peek() {
        //println!("{first}"); //works
        //println!("{tokens:?}"); // works
        println!("{first}\n{tokens:?}"); //compile error
    }
}
error[E0502]: cannot borrow `tokens` as immutable because it is also borrowed as mutable
 --> src/main.rs:7:29
  |
4 |     if let Some(first) = tokens.peek() {
  |                          ------------- mutable borrow occurs here
...
7 |         println!("{first}\n{tokens:?}"); //error
  |         --------------------^^^^^^-----
  |         |                   |
  |         |                   immutable borrow occurs here
  |         mutable borrow later used here

If I un-comment the two printlns, and comment the erroneous one. then It works. This lead me to adding a clone let first = first.clone();, before the printlns. This fixed it, but I am wondering if there is a better way.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The simplest way to achieve this is to just collect the vector, then get the first element:

let tokens: Vec<_> = line.split_whitespace().collect();
if let Some(first) = tokens.first() {
    println!("{first}\n{tokens:?}");
}

Note the type of tokens will be Vec<&str> — a vector of string slices that are borrowed from line. If you instead want a vector of owned strings (Vec<String>), then you need to map each element to an owned string:

let tokens: Vec<_> = line.split_whitespace().map(|s| s.to_owned()).collect();
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading