Проблемы с графиком Rust и собственниками - PullRequest
1 голос
/ 25 мая 2019

Я пытаюсь создать хэш-карту, читая файл. Ниже приведен код, который я написал. Суть в том, что мне нужно сохранить subset_description до следующей итерации, чтобы я мог сохранить его в hasmap и, наконец, вернуть hashmap.

fn myfunction(filename: &Path) -> io::Result<HashMap<&str, &str>> {
    let mut SIF = HashMap::new();
    let file = File::open(filename).unwrap();
    let mut subset_description = "";
    for line in BufReader::new(file).lines() {
        let thisline = line?;
        let line_split: Vec<&str> = thisline.split("=").collect();
        subset_description = if thisline.starts_with("a") {
            let subset_description = line_split[1].trim();
            subset_description
        } else {
            ""
        };
        let subset_ids = if thisline.starts_with("b") {
            let subset_ids = line_split[1].split(",");
            let subset_ids = subset_ids.map(|s| s.trim());
            subset_ids.collect()
        } else {
            Vec::new()
        };
        for k in subset_ids {
            SIF.insert(k, subset_description);
            println!("");
        }
        if thisline.starts_with("!dataset_table_begin") {
            break;
        }
    }
    Ok(SIF)
}

Я получаю сообщение об ошибке ниже и не могу решить эту проблему

error[E0515]: cannot return value referencing local variable `thisline`
  --> src/main.rs:73:5
   |
51 |         let line_split: Vec<&str> = thisline.split("=").collect();
   |                                     -------- `thisline` is borrowed here
...
73 |     Ok(SIF)
   |     ^^^^^^^ returns a value referencing data owned by the current function

1 Ответ

0 голосов
/ 25 мая 2019

Проблема заключается в гарантиях, которые Rust дает от вашего имени. Корень проблемы можно увидеть в следующем. Вы читаете файл и манипулируете его содержимым в HashMap, и вы пытаетесь вернуть ссылку на прочитанные вами данные. Но, возвращая ссылку, вы должны будете гарантировать, что строки в файле не будут изменены позже, что вы, естественно, не можете сделать.

В терминах Rust вы продолжаете пытаться возвращать ссылки на локальные переменные, которые удаляются в конце функции, что эффективно оставит вас с висячими указателями. Вот изменения, которые я сделал, даже если они не самые эффективные, они компилируются.

fn myfunction(filename: &Path) -> io::Result<HashMap<String, String>> {
    let mut SIF = HashMap::new();
    let file = File::open(filename).unwrap();
    let mut subset_description = "";
    for line in BufReader::new(file).lines() {
        let thisline = line?;
        let line_split: Vec<String> = thisline.split("=").map(|s| s.to_string()).collect();
        subset_description = if thisline.starts_with("a") {
            let subset_description = line_split[1].trim();
            subset_description
        } else {
            ""
        };
        let subset_ids = if thisline.starts_with("b") {
            let subset_ids = line_split[1].split(",");
            let subset_ids = subset_ids.map(|s| s.trim());
            subset_ids.map(|s| s.to_string()).collect()
        } else {
            Vec::new()
        };
        for k in subset_ids {
            SIF.insert(k, subset_description.to_string());
            println!("");
        }
        if thisline.starts_with("!dataset_table_begin") {
            break;
        }
    }
    Ok(SIF)
}

Как видите, теперь вы отдаете владение строками в возвращаемое значение. Это достигается путем изменения типа возвращаемого значения и использования функции to_string(), чтобы передать владение локальными строками HashMap.

Существует аргумент, что to_string() медленный, поэтому вы можете изучить использование в или to_owned(), но, поскольку я не разбираюсь в этих конструкциях, я не могу помочь вам в оптимизации.

...