Andrew
Andrew

Reputation: 13853

Use flat_map to convert Vec<u8> to Vec<char>

I'm stuck in a similar situation to Borrow-check error with variable not living long enough in nested lambda but am unable to figure out how my situation differs:

let mut vec = vec![vec![0u8, 1u8], vec![2u8, 3u8], vec![4u8, 5u8]];
vec.iter().map(|row| {
    row.iter()
        .map(|d| format!("{:04b}", d))
        .flat_map(|s| s.chars())
        .collect::<Vec<_>>()
});

Which gives the error:

error[E0597]: `s` does not live long enough
 --> src/main.rs:6:35
  |
6 |             .flat_map(|s| s.chars())
  |                           -       ^ `s` dropped here while still borrowed
  |                           |
  |                           borrow occurs here
7 |             .collect::<Vec<_>>()
  |                                - borrowed value needs to live until here

I worked around it by creating a new Vec and appending, but I'm unclear why the first approach did not work.

let mut tmp = vec![];
vec.iter()
    .map(|d| format!("{:04b}", d))
    .for_each(|s| {tmp.append(&mut s.chars().collect::<Vec<_>>());});

Upvotes: 4

Views: 974

Answers (1)

Sven Marnach
Sven Marnach

Reputation: 602145

You first map the closure |d| format!("{:04b}", d) over your iterator, yielding Strings, which own their data, so this works perfectly find. The flat_map() in the next step calls .chars() on each String. This implicitly derefrences the String to an &str, and creates a Chars iterator referencing this borrow. But now we have a problem – nobody is owning the String that we borrowed anymore.

One workaround is to store a temporary vector of Strings:

let mut vec = vec![vec![0u8, 1u8], vec![2u8, 3u8], vec![4u8, 5u8]];
vec.iter().map(|row| {
    let strings: Vec<_> = row
        .iter()
        .map(|d| format!("{:04b}", d))
        .collect();
    strings
        .iter()
        .flat_map(|s| s.chars())
        .collect::<Vec<_>>()
});

Now we have an owner for the intermediary Strings, and everything works fine again.

Upvotes: 3

Related Questions