Skip to content

Commit 7bc950c

Browse files
committed
Refactor some hashmap code into a new private function mangle()
Add new private hashmap function fn mangle(&mut self, k: K, not_found: &fn(&K) -> V, found: &fn(&K, &mut V)) -> uint Rewrite find_or_insert() and find_or_insert_with() on top of mangle(). Also take the opportunity to change the return type of find_or_insert() and find_or_insert_with() to &'a mut V. This fixes #6394.
1 parent 44af506 commit 7bc950c

File tree

1 file changed

+21
-37
lines changed

1 file changed

+21
-37
lines changed

src/libstd/hashmap.rs

Lines changed: 21 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -425,9 +425,10 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
425425
}
426426
}
427427

428-
/// Return the value corresponding to the key in the map, or insert
429-
/// and return the value if it doesn't exist.
430-
pub fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a V {
428+
/// Modify and return the value corresponding to the key in the map, or
429+
/// insert and return a new value if it doesn't exist.
430+
pub fn mangle<'a,A>(&'a mut self, k: K, a: A, not_found: &fn(&K, A) -> V,
431+
found: &fn(&K, &mut V, A)) -> &'a mut V {
431432
if self.size >= self.resize_at {
432433
// n.b.: We could also do this after searching, so
433434
// that we do not resize if this call to insert is
@@ -441,46 +442,29 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
441442
let hash = k.hash_keyed(self.k0, self.k1) as uint;
442443
let idx = match self.bucket_for_key_with_hash(hash, &k) {
443444
TableFull => fail!("Internal logic error"),
444-
FoundEntry(idx) => idx,
445+
FoundEntry(idx) => { found(&k, self.mut_value_for_bucket(idx), a); idx }
445446
FoundHole(idx) => {
446-
self.buckets[idx] = Some(Bucket{hash: hash, key: k,
447-
value: v});
447+
let v = not_found(&k, a);
448+
self.buckets[idx] = Some(Bucket{hash: hash, key: k, value: v});
448449
self.size += 1;
449450
idx
450-
},
451+
}
451452
};
452453

453-
self.value_for_bucket(idx)
454+
self.mut_value_for_bucket(idx)
455+
}
456+
457+
/// Return the value corresponding to the key in the map, or insert
458+
/// and return the value if it doesn't exist.
459+
pub fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a mut V {
460+
self.mangle(k, v, |_k, a| a, |_k,_v,_a| ())
454461
}
455462

456463
/// Return the value corresponding to the key in the map, or create,
457464
/// insert, and return a new value if it doesn't exist.
458465
pub fn find_or_insert_with<'a>(&'a mut self, k: K, f: &fn(&K) -> V)
459-
-> &'a V {
460-
if self.size >= self.resize_at {
461-
// n.b.: We could also do this after searching, so
462-
// that we do not resize if this call to insert is
463-
// simply going to update a key in place. My sense
464-
// though is that it's worse to have to search through
465-
// buckets to find the right spot twice than to just
466-
// resize in this corner case.
467-
self.expand();
468-
}
469-
470-
let hash = k.hash_keyed(self.k0, self.k1) as uint;
471-
let idx = match self.bucket_for_key_with_hash(hash, &k) {
472-
TableFull => fail!("Internal logic error"),
473-
FoundEntry(idx) => idx,
474-
FoundHole(idx) => {
475-
let v = f(&k);
476-
self.buckets[idx] = Some(Bucket{hash: hash, key: k,
477-
value: v});
478-
self.size += 1;
479-
idx
480-
},
481-
};
482-
483-
self.value_for_bucket(idx)
466+
-> &'a mut V {
467+
self.mangle(k, (), |k,_a| f(k), |_k,_v,_a| ())
484468
}
485469

486470
/// Calls a function on each element of a hash map, destroying the hash
@@ -763,15 +747,15 @@ mod test_map {
763747
#[test]
764748
fn test_find_or_insert() {
765749
let mut m = HashMap::new::<int, int>();
766-
assert_eq!(m.find_or_insert(1, 2), &2);
767-
assert_eq!(m.find_or_insert(1, 3), &2);
750+
assert_eq!(*m.find_or_insert(1, 2), 2);
751+
assert_eq!(*m.find_or_insert(1, 3), 2);
768752
}
769753

770754
#[test]
771755
fn test_find_or_insert_with() {
772756
let mut m = HashMap::new::<int, int>();
773-
assert_eq!(m.find_or_insert_with(1, |_| 2), &2);
774-
assert_eq!(m.find_or_insert_with(1, |_| 3), &2);
757+
assert_eq!(*m.find_or_insert_with(1, |_| 2), 2);
758+
assert_eq!(*m.find_or_insert_with(1, |_| 3), 2);
775759
}
776760

777761
#[test]

0 commit comments

Comments
 (0)