此代码有效:
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;
});
Run Code Online (Sandbox Code Playgroud)
此代码失败并显示消息:"无法移出,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
});
Run Code Online (Sandbox Code Playgroud)
She*_*ter 15
你不能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);
}
Run Code Online (Sandbox Code Playgroud)
在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);
}
Run Code Online (Sandbox Code Playgroud)
您还可以阻止借款持续超出其所需的界限:
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);
}
Run Code Online (Sandbox Code Playgroud)
我以为Rust会知道
counter一旦acc返回就会超出范围
这是可以理解的,涉及非词汇生命周期的讨论."好"的消息是Rust在被引用的东西移动时,引用如何工作是一致的.在这种情况下,您将累加器移动到"输出槽".你也可以通过普通函数看到这个:
fn foo(mut s: Vec<u8>) -> Vec<u8> {
let borrow = &mut s[0];
s
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
但实际上,它与移动引用变量完全相同:
fn main() {
let mut s = Vec::<u8>::new();
let borrow = &mut s[0];
let s2 = s;
}
Run Code Online (Sandbox Code Playgroud)
这两个都在NLL之前失败并且之后工作.
| 归档时间: |
|
| 查看次数: |
1972 次 |
| 最近记录: |