@@ -35,7 +35,16 @@ pub trait Map<K:Eq IterBytes Hash Copy, V: Copy> {
35
35
* If the map contains a value for the key, use the function
36
36
* to set a new value.
37
37
*/
38
- fn insert_with_key ( ff : fn ( K , V , V ) -> V , key : K , value : V ) -> bool ;
38
+ fn insert_with_key ( key : K , newval : V , ff : fn ( K , V , V ) -> V ) -> bool ;
39
+
40
+ /**
41
+ * Add a value to the map.
42
+ *
43
+ * If the map contains a value for the key, use the function
44
+ * to set a new value. (Like insert_with_key, but with a function
45
+ * of only values.)
46
+ */
47
+ fn insert_with ( key : K , newval : V , ff : fn ( V , V ) -> V ) -> bool ;
39
48
40
49
/// Returns true if the map contains a value for the specified key
41
50
pure fn contains_key ( key : K ) -> bool ;
@@ -272,12 +281,57 @@ pub mod chained {
272
281
}
273
282
}
274
283
275
- fn insert_with_key ( ff : fn ( K , V , V ) -> V , key : K , val : V ) -> bool {
276
- // this can be optimized but first lets see if it compiles...
284
+ fn insert_with_key ( key : K , newval : V , ff : fn ( K , V , V ) -> V ) -> bool {
285
+ /*
277
286
match self.find(key) {
278
287
None => return self.insert(key, val),
279
288
Some(copy orig) => return self.insert(key, ff(key, orig, val))
280
289
}
290
+ */
291
+
292
+ let hash = key. hash_keyed ( 0 , 0 ) as uint ;
293
+ match self . search_tbl ( & key, hash) {
294
+ NotFound => {
295
+ self . count += 1 u;
296
+ let idx = hash % vec:: len ( self . chains ) ;
297
+ let old_chain = self . chains [ idx] ;
298
+ self . chains [ idx] = Some ( @Entry {
299
+ hash : hash,
300
+ key : key,
301
+ value : newval,
302
+ next : old_chain} ) ;
303
+
304
+ // consider rehashing if more 3/4 full
305
+ let nchains = vec:: len ( self . chains ) ;
306
+ let load = { num : ( self . count + 1 u) as int ,
307
+ den: nchains as int } ;
308
+ if !util:: rational_leq ( load, { num: 3 , den: 4 } ) {
309
+ self . rehash ( ) ;
310
+ }
311
+
312
+ return true ;
313
+ }
314
+ FoundFirst ( idx, entry) => {
315
+ self . chains [ idx] = Some ( @Entry {
316
+ hash : hash,
317
+ key : key,
318
+ value : ff ( key, entry. value , newval) ,
319
+ next : entry. next } ) ;
320
+ return false ;
321
+ }
322
+ FoundAfter ( prev, entry) => {
323
+ prev. next = Some ( @Entry {
324
+ hash : hash,
325
+ key : key,
326
+ value : ff ( key, entry. value , newval) ,
327
+ next : entry. next } ) ;
328
+ return false ;
329
+ }
330
+ }
331
+ }
332
+
333
+ fn insert_with ( key : K , newval : V , ff : fn ( V , V ) -> V ) -> bool {
334
+ return self . insert_with_key ( key, newval, |_k, v, v1| ff ( v, v1) ) ;
281
335
}
282
336
283
337
pure fn get ( k : K ) -> V {
@@ -463,12 +517,16 @@ impl<K: Eq IterBytes Hash Copy, V: Copy> @Mut<LinearMap<K, V>>:
463
517
}
464
518
}
465
519
466
- fn insert_with_key ( ff : fn ( K , V , V ) -> V , key : K , val : V ) -> bool {
467
- match self . find ( key) {
468
- None => return self . insert ( key, val) ,
469
- Some ( copy orig) => return self . insert ( key, ff ( key, orig, val) ) ,
470
- }
471
- }
520
+ fn insert_with_key ( key : K , newval : V , ff : fn ( K , V , V ) -> V ) -> bool {
521
+ match self . find ( key) {
522
+ None => return self . insert ( key, newval) ,
523
+ Some ( copy orig) => return self . insert ( key, ff ( key, orig, newval) )
524
+ }
525
+ }
526
+
527
+ fn insert_with ( key : K , newval : V , ff : fn ( V , V ) -> V ) -> bool {
528
+ return self . insert_with_key ( key, newval, |_k, v, v1| ff ( v, v1) ) ;
529
+ }
472
530
473
531
fn remove ( key : K ) -> bool {
474
532
do self . borrow_mut |p| {
@@ -778,20 +836,30 @@ mod tests {
778
836
fn test_insert_with_key() {
779
837
let map = map::HashMap::<~str, uint>();
780
838
781
- fn inc(k: ~str, v0: uint, v1: uint) -> uint {
839
+ // given a new key, initialize it with this new count, given
840
+ // given an existing key, add more to its count
841
+ fn addMoreToCount(_k: ~str, v0: uint, v1: uint) -> uint {
842
+ v0 + v1
843
+ }
844
+
845
+ fn addMoreToCount_simple(v0: uint, v1: uint) -> uint {
782
846
v0 + v1
783
847
}
784
848
785
- map.insert_with_key(inc, ~" cat", 1 ) ;
786
- map. insert_with_key ( inc, ~"mongoose", 1 ) ;
787
- map. insert_with_key ( inc, ~"cat", 7 ) ;
788
- map. insert_with_key ( inc, ~"ferret", 3 ) ;
789
- map. insert_with_key ( inc, ~"cat", 2 ) ;
849
+ // count the number of several types of animal,
850
+ // adding in groups as we go
851
+ map.insert_with(~" cat", 1 , addMoreToCount_simple) ;
852
+ map. insert_with_key ( ~"mongoose", 1 , addMoreToCount) ;
853
+ map. insert_with ( ~"cat", 7 , addMoreToCount_simple) ;
854
+ map. insert_with_key ( ~"ferret", 3 , addMoreToCount) ;
855
+ map. insert_with_key ( ~"cat", 2 , addMoreToCount) ;
790
856
857
+ // check the total counts
791
858
assert 10 == option:: get ( map. find ( ~"cat") ) ;
792
859
assert 3 == option:: get ( map. find ( ~"ferret") ) ;
793
860
assert 1 == option:: get ( map. find ( ~"mongoose") ) ;
794
861
862
+ // sadly, no mythical animals were counted!
795
863
assert None == map. find ( ~"unicorn") ;
796
864
}
797
865
}
0 commit comments