问题描述
我正在计算一个单词在 Macbeth 中出现的次数:
I am counting the number of times a word appears in Macbeth:
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);
}
Rust 对此嗤之以鼻,说:
Rust barfs on this, saying:
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()
可以解决它.当问题是 w
时,我不明白为什么 Rust 编译器将责任归咎于 l
.我该如何推断 w
是这里的问题?
The actual problem is that w
is a reference, and so changing it to w.to_string()
solves it. I don't get why the Rust compiler is pointing the blame at l
, when the issue is w
. How am I supposed to infer that w
is the problem here?
推荐答案
这不是,真的.再次查看错误消息:
It's not, really. Review the error message again:
for w in l.unwrap().split_whitespace() {
---------- temporary value created here
错误标记指向 l
上的 unwrap
调用.
The error marker is pointing to the call of unwrap
on l
.
当问题是 w
这不是,真的.l
是 Result
类型.当您调用 unwrap
时,您会得到一个 String
,然后 split_whitespace
返回对该字符串的引用.这些引用仅与字符串一样长,但您的代码尝试将它们放入一个比字符串寿命更长的哈希图中.问题是 l.unwrap()
的寿命不够长,而 w
只是对没有的东西的引用活得够久.
It's not, really. l
is of type Result<String>
. When you call unwrap
, you get a String
, and then split_whitespace
returns references to that string. These references live only as long as the string, but your code tries to put them into a hashmap that will live longer than the string. The problem is that the l.unwrap()
doesn't live long enough, and w
is just a reference to the thing that doesn't live long enough.
概念上,这和这段代码是一样的问题:
Conceptually, it's the same problem as this code:
use std::collections::HashMap;
fn main() {
let mut counts = HashMap::new();
{
let s = String::from("hello world");
counts.insert(&s, 0);
}
println!("{:?}", counts);
}
这也指向 s
并说它的寿命不够长(因为它没有).
Which also points to s
and says it doesn't live long enough (because it doesn't).
正确的解决方案是将每个单词转换成一个拥有的 String
,然后 HashMap
可以保存:
The correct solution is to convert each word into an owned String
which the HashMap
can then hold:
for l in reader.lines() {
for w in l.unwrap().split_whitespace() {
counts.entry(w.to_string()).or_insert(0) += 1;
}
}
这篇关于“借来的价值活得不够久"似乎责怪错误的事情的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!