Search code examples
rustio

Missing lifetime specifier when returning Vec<Vec<&str>> of strings from a file


I am trying to write a function that iterates over a text file line by line and splits the sentences into a vector. Then those split lines are put in another vector and returned.

use std::fs::File;
use std::io::{ self, BufRead };

use rand::seq::SliceRandom;
use rand::thread_rng;


pub fn ParseWords() -> Vec<Vec<&str>> {
    let file = File::open("./words.txt".to_string()).unwrap();
    let mut words = Vec::new();

    // Iterate over the lines of the file.
    for line in io::BufReader::new(file).lines() {
        words.push(line.unwrap().split("|").collect::<Vec<&str>>());
    }

    // Do a bit of shuffling.
    let mut rng = thread_rng();
    words.shuffle(&mut rng);

    return words.clone()
}

I have went down a rabbit hole putting in the compiler's suggestions and consulted chatgpt but I am not really getting anywhere. When compiling I'm getting this:

error[E0106]: missing lifetime specifier
 --> src\parser.rs:8:32
  |
8 | pub fn ParseWords() -> Vec<Vec<&str>> {
  |                                ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
  |
8 | pub fn ParseWords() -> Vec<Vec<&'static str>> {
  |                                

Solution

  • Whenever a function has no lifetimes in its arguments and returns a non-static lifetime, you're almost certainly doing something wrong. The only time you're likely to see it is in Box::leak, which is used to leak memory. That's not applicable here.

    So, you need to return owned values. The owned version of &str is String, so the function return becomes Vec<Vec<String>>.

    Then you need to change your iterator to make strings.

    line.unwrap().split('|').map(|s| s.to_string()).collect()
    

    Cleaning up everything else, we get:

    pub fn parse_words() -> Vec<Vec<String>> {
        let file = File::open("./words.txt").unwrap();
    
        // Iterate over the lines of the file.
        let mut words: Vec<Vec<_>> = io::BufReader::new(file)
            .lines()
            .map(|line| line.unwrap().split('|').map(|s| s.to_string()).collect())
            .collect();
    
        // Do a bit of shuffling.
        let mut rng = thread_rng();
        words.shuffle(&mut rng);
    
        words
    }