我在数一个单词出现在麦克白身上的次数:

use std::io::{BufRead, BufReader};
use std::fs::File;
use std::collections::HashMap;

fn main() {
    let f = File::open("macbeth.txt").unwrap();
    let reader = BufReader::new(f);
    let mut counts = HashMap::new();

    for l in reader.lines() {
        for w in l.unwrap().split_whitespace() {
            let count = counts.entry(w).or_insert(0);
            *count += 1;
        }
    }

    println!("{:?}", counts);
}

锈在上面,说:
error[E0597]: borrowed value does not live long enough
  --> src/main.rs:14:9
   |
11 |         for w in l.unwrap().split_whitespace() {
   |                  ---------- temporary value created here
...
14 |         }
   |         ^ temporary value dropped here while still borrowed
...
18 | }
   | - temporary value needs to live until here
   |
   = note: consider using a `let` binding to increase its lifetime

实际的问题是w是一个引用,因此将其更改为w.to_string()可以解决这个问题。当问题是l时,我不明白为什么Rust编译器将责任指向w。我怎么能推断出这里的问题是w

最佳答案

把责任归咎于l
不是,真的。再次查看错误消息:

     for w in l.unwrap().split_whitespace() {
              ---------- temporary value created here

错误标记指向unwrapl的调用。
当问题w
不是,真的。l属于Result<String>类型。当您调用unwrap时,会得到一个String,然后split_whitespace返回对该字符串的引用。这些引用的有效期仅与字符串的有效期一样长,但您的代码尝试将它们放入比字符串有效期更长的hashmap中。问题是l.unwrap()的寿命不够长,而w只是指寿命不够长的东西。
从概念上讲,这和这段代码是同一个问题:
use std::collections::HashMap;

fn main() {
    let mut counts = HashMap::new();

    {
        let s = String::from("hello world");
        counts.insert(&s, 0);
    }

    println!("{:?}", counts);
}

它还指向s并说它活得不够长(因为它活得不够长)。
正确的解决方案是将每个单词转换为String所有,然后HashMap可以保存该单词:
for l in reader.lines() {
    for w in l.unwrap().split_whitespace() {
        counts.entry(w.to_string()).or_insert(0) += 1;
    }
}

关于rust - “借来的值(value)不能活得足够长”似乎归咎于错误的事情,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47804498/

10-12 03:20