Skip to content

Commit f33767f

Browse files
committed
---
yaml --- r: 65532 b: refs/heads/master c: 14c3310 h: refs/heads/master v: v3
1 parent 57fd562 commit f33767f

File tree

2 files changed

+36
-37
lines changed

2 files changed

+36
-37
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 96f6f29477cbe8ce0f779f493b243fc657b6e22e
2+
refs/heads/master: 14c331053ea9d2661cfd9c81351f4b3815cf5e3d
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 18e3db7392d2d0697b7e27d6d986139960144d85
55
refs/heads/try: 7b78b52e602bb3ea8174f9b2006bff3315f03ef9

trunk/src/libstd/hashmap.rs

Lines changed: 35 additions & 36 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,37 @@ 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-
};
466+
-> &'a mut V {
467+
self.mangle(k, (), |k,_a| f(k), |_k,_v,_a| ())
468+
}
482469

483-
self.value_for_bucket(idx)
470+
/// Insert a key-value pair into the map if the key is not already present.
471+
/// Otherwise, modify the existing value for the key.
472+
/// Returns the new or modified value for the key.
473+
pub fn insert_or_update_with<'a>(&'a mut self, k: K, v: V,
474+
f: &fn(&K, &mut V)) -> &'a mut V {
475+
self.mangle(k, v, |_k,a| a, |k,v,_a| f(k,v))
484476
}
485477

486478
/// Calls a function on each element of a hash map, destroying the hash
@@ -763,15 +755,22 @@ mod test_map {
763755
#[test]
764756
fn test_find_or_insert() {
765757
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);
758+
assert_eq!(*m.find_or_insert(1, 2), 2);
759+
assert_eq!(*m.find_or_insert(1, 3), 2);
768760
}
769761

770762
#[test]
771763
fn test_find_or_insert_with() {
772764
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);
765+
assert_eq!(*m.find_or_insert_with(1, |_| 2), 2);
766+
assert_eq!(*m.find_or_insert_with(1, |_| 3), 2);
767+
}
768+
769+
#[test]
770+
fn test_insert_or_update_with() {
771+
let mut m = HashMap::new::<int, int>();
772+
assert_eq!(*m.insert_or_update_with(1, 2, |_,x| *x+=1), 2);
773+
assert_eq!(*m.insert_or_update_with(1, 2, |_,x| *x+=1), 3);
775774
}
776775

777776
#[test]

0 commit comments

Comments
 (0)