此代码有效:
let stdin = std::io::stdin();
let mut rdr = csv::Reader::from_reader(stdin);
let mut hmap = HashMap::<String, u64>::new();
rdr.records()
.map(|r| r.unwrap())
.fold((), |_, item| {
// TODO: Is there a way not to have to copy item[col] every time?
let counter = hmap.entry(item[col].to_string()).or_insert(0);
*counter += 1;
});
该代码失败,并显示以下消息:“acc
由于被借用而无法移出”
let stdin = std::io::stdin();
let mut rdr = csv::Reader::from_reader(stdin);
let hmap = rdr.records()
.map(|r| r.unwrap())
.fold(HashMap::<String, u64>::new(), |mut acc, item| {
// TODO: Is there a way not to have to copy item[col] every time?
let counter = acc.entry(item[col].to_string()).or_insert(0);
*counter += 1;
acc
});
您无法acc
从闭包中返回,因为您有对它的可变借用,而该借用仍然存在(counter
)。
这是Rust编译器(特别是借用检查器)的限制。当非词汇的寿命被启用,原来的代码将工作:
#![feature(nll)]
use std::collections::HashMap;
fn main() {
let hmap = vec![1, 2, 3].iter().fold(HashMap::new(), |mut acc, _| {
let counter = acc.entry("foo".to_string()).or_insert(0);
*counter += 1;
acc
});
println!("{:?}", hmap);
}
在NLL之前,编译器对借用的持续时间过于保守。要变通解决此问题,您可以引入一个新范围来约束可变借位:
use std::collections::HashMap;
fn main() {
let hmap = vec![1, 2, 3].iter().fold(HashMap::new(), |mut acc, _| {
{
let counter = acc.entry("foo".to_string()).or_insert(0);
*counter += 1;
}
acc
});
println!("{:?}", hmap);
}
您还可以防止借贷持续超出其所需的行数:
use std::collections::HashMap;
fn main() {
let hmap = vec![1, 2, 3].iter().fold(HashMap::new(), |mut acc, _| {
*acc.entry("foo".to_string()).or_insert(0) += 1;
acc
});
println!("{:?}", hmap);
}
我以为Rust知道
counter
一旦acc
返回,它将超出范围
这是可以理解的,并且与非词汇生命周期的讨论有关。“好消息”是,当被引用的事物移动时,Rust一直对引用的工作方式保持一致。在这种情况下,要将累加器移至“输出插槽”。您还可以通过简单的功能看到这一点:
fn foo(mut s: Vec<u8>) -> Vec<u8> {
let borrow = &mut s[0];
s
}
fn main() {}
但实际上,这完全与移动引用的变量相同:
fn main() {
let mut s = Vec::<u8>::new();
let borrow = &mut s[0];
let s2 = s;
}
这两种方法在NLL之前都失败了,然后才起作用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句