rust - How to fold using a HashMap as an accumulator? -
this code works:
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: there way not have copy item[col] every time? let counter = hmap.entry(item[col].to_string()).or_insert(0); *counter += 1; });
this code fails message: "cannot move out of acc
because borrowed"
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: there way not have copy item[col] every time? let counter = acc.entry(item[col].to_string()).or_insert(0); *counter += 1; acc });
you cannot return acc
closure because have mutable borrow still exists (counter
).
you can introduce new scope constrain mutable borrow:
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); }
or can remove borrow reducing 1 line:
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); }
i assumed rust know
counter
go out of scope onceacc
returned
this understandable, rust being consistent how references work when thing being referenced moves. in case, moving accumulator "output slot". can see plain functions well:
fn foo(mut s: vec<u8>) -> vec<u8> { let borrow = &mut s[0]; s } fn main() {}
but really, it's same moving referred-to variable @ all:
fn main() { let mut s = vec::<u8>::new(); let borrow = &mut s[0]; let s2 = s; }
Comments
Post a Comment