From 66e50892c1840a030892b2dc6480d42635990b0c Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Mon, 21 Jan 2013 17:12:35 -0500 Subject: [PATCH 1/4] style fix --- src/libstd/treemap.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index 1b20b35bda1..9e61658141c 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -64,9 +64,7 @@ impl TreeMap: Eq { true } } - pure fn ne(&self, other: &TreeMap) -> bool { - !self.eq(other) - } + pure fn ne(&self, other: &TreeMap) -> bool { !self.eq(other) } } impl TreeMap { From ffb9049274beaac8ddde6b9632d8c9ac7715f9d1 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Mon, 21 Jan 2013 17:25:57 -0500 Subject: [PATCH 2/4] add a Mutable container trait with clear --- src/libcore/container.rs | 7 +++++- src/libcore/send_map.rs | 23 +++++++++++-------- src/libstd/priority_queue.rs | 9 +++++--- src/libstd/treemap.rs | 43 +++++++++++++++++++++++++++++++++++- 4 files changed, 68 insertions(+), 14 deletions(-) diff --git a/src/libcore/container.rs b/src/libcore/container.rs index 619622ceb95..f8ccd0148ab 100644 --- a/src/libcore/container.rs +++ b/src/libcore/container.rs @@ -10,7 +10,12 @@ //! Container traits -pub trait Set { +pub trait Mutable { + /// Clear the container, removing all values. + fn clear(&mut self); +} + +pub trait Set: Mutable { /// Return true if the set contains a value pure fn contains(&self, value: &T) -> bool; diff --git a/src/libcore/send_map.rs b/src/libcore/send_map.rs index 1e526c5d08f..5f440aa6d37 100644 --- a/src/libcore/send_map.rs +++ b/src/libcore/send_map.rs @@ -31,7 +31,6 @@ pub trait SendMap { fn pop(&mut self, k: &K) -> Option; fn swap(&mut self, k: K, +v: V) -> Option; fn consume(&mut self, f: fn(K, V)); - fn clear(&mut self); pure fn len(&const self) -> uint; pure fn is_empty(&const self) -> bool; pure fn contains_key(&const self, k: &K) -> bool; @@ -47,7 +46,7 @@ pub trait SendMap { /// Open addressing with linear probing. pub mod linear { use iter::BaseIter; - use container::Set; + use container::{Mutable, Set}; use cmp::Eq; use cmp; use hash::Hash; @@ -279,6 +278,15 @@ pub mod linear { } } + impl LinearMap: Mutable { + fn clear(&mut self) { + for uint::range(0, self.buckets.len()) |idx| { + self.buckets[idx] = None; + } + self.size = 0; + } + } + impl LinearMap { fn insert(&mut self, k: K, v: V) -> bool { if self.size >= self.resize_at { @@ -347,13 +355,6 @@ pub mod linear { } } - fn clear(&mut self) { - for uint::range(0, self.buckets.len()) |idx| { - self.buckets[idx] = None; - } - self.size = 0; - } - pure fn len(&const self) -> uint { self.size } @@ -482,6 +483,10 @@ pub mod linear { } } + impl LinearSet: Mutable { + fn clear(&mut self) { self.map.clear() } + } + impl LinearSet: Set { /// Return true if the set contains a value pure fn contains(&self, value: &T) -> bool { diff --git a/src/libstd/priority_queue.rs b/src/libstd/priority_queue.rs index b9c040de42a..0ff40b6421a 100644 --- a/src/libstd/priority_queue.rs +++ b/src/libstd/priority_queue.rs @@ -10,6 +10,7 @@ //! A priority queue implemented with a binary heap +use core::container::Mutable; use core::cmp::Ord; use core::prelude::*; use core::ptr::addr_of; @@ -24,6 +25,11 @@ pub struct PriorityQueue { priv data: ~[T], } +impl PriorityQueue: Mutable { + /// Drop all items from the queue + fn clear(&mut self) { self.data.truncate(0) } +} + impl PriorityQueue { /// Returns the greatest item in the queue - fails if empty pure fn top(&self) -> &self/T { &self.data[0] } @@ -51,9 +57,6 @@ impl PriorityQueue { vec::reserve_at_least(&mut self.data, n) } - /// Drop all items from the queue - fn clear(&mut self) { self.data.truncate(0) } - /// Pop the greatest item from the queue - fails if empty fn pop(&mut self) -> T { let mut item = self.data.pop(); diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index 9e61658141c..74a14b7903c 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -14,7 +14,7 @@ #[forbid(deprecated_mode)]; -use core::container::Set; +use core::container::{Mutable, Set}; use core::cmp::{Eq, Ord}; use core::option::{Option, Some, None}; use core::prelude::*; @@ -67,6 +67,14 @@ impl TreeMap: Eq { pure fn ne(&self, other: &TreeMap) -> bool { !self.eq(other) } } +impl TreeMap: Mutable { + /// Clear the map, removing all key-value pairs. + fn clear(&mut self) { + self.root = None; + self.length = 0 + } +} + impl TreeMap { /// Create an empty TreeMap static pure fn new() -> TreeMap { TreeMap{root: None, length: 0} } @@ -196,6 +204,11 @@ impl TreeSet: Eq { pure fn ne(&self, other: &TreeSet) -> bool { self.map != other.map } } +impl TreeSet: Mutable { + /// Clear the set, removing all values. + fn clear(&mut self) { self.map.clear() } +} + impl TreeSet: Set { /// Return true if the set contains a value pure fn contains(&self, value: &T) -> bool { @@ -624,6 +637,20 @@ mod test_treemap { assert m.find(&2).unwrap() == &11; } + #[test] + fn test_clear() { + let mut m = TreeMap::new(); + m.clear(); + assert m.insert(5, 11); + assert m.insert(12, -3); + assert m.insert(19, 2); + m.clear(); + assert m.find(&5).is_none(); + assert m.find(&12).is_none(); + assert m.find(&19).is_none(); + assert m.is_empty(); + } + #[test] fn u8_map() { let mut m = TreeMap::new(); @@ -844,6 +871,20 @@ mod test_treemap { mod test_set { use super::*; + #[test] + fn test_clear() { + let mut s = TreeSet::new(); + s.clear(); + assert s.insert(5); + assert s.insert(12); + assert s.insert(19); + s.clear(); + assert !s.contains(&5); + assert !s.contains(&12); + assert !s.contains(&19); + assert s.is_empty(); + } + #[test] fn test_disjoint() { let mut xs = TreeSet::new(); From d635a6e506012ad4d427578e394aa2041e7dbdfb Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Mon, 21 Jan 2013 18:22:03 -0500 Subject: [PATCH 3/4] add a container::Map trait --- src/libcore/container.rs | 26 +++++++++++++ src/libcore/send_map.rs | 81 +++++++++++++++------------------------- src/libstd/treemap.rs | 66 ++++++++++++++++---------------- 3 files changed, 91 insertions(+), 82 deletions(-) diff --git a/src/libcore/container.rs b/src/libcore/container.rs index f8ccd0148ab..dd556aec45f 100644 --- a/src/libcore/container.rs +++ b/src/libcore/container.rs @@ -10,11 +10,37 @@ //! Container traits +#[forbid(deprecated_mode)]; +#[forbid(deprecated_pattern)]; + pub trait Mutable { /// Clear the container, removing all values. fn clear(&mut self); } +pub trait Map: Mutable { + /// Return true if the map contains a value for the specified key + pure fn contains_key(&self, key: &K) -> bool; + + /// Visit all key-value pairs + pure fn each(&self, f: fn(&K, &V) -> bool); + + /// Visit all keys + pure fn each_key(&self, f: fn(&K) -> bool); + + /// Visit all values + pure fn each_value(&self, f: fn(&V) -> bool); + + /// Insert a key-value pair into the map. An existing value for a + /// key is replaced by the new value. Return true if the key did + /// not already exist in the map. + fn insert(&mut self, key: K, value: V) -> bool; + + /// Remove a key-value pair from the map. Return true if the key + /// was present in the map, otherwise false. + fn remove(&mut self, key: &K) -> bool; +} + pub trait Set: Mutable { /// Return true if the set contains a value pure fn contains(&self, value: &T) -> bool; diff --git a/src/libcore/send_map.rs b/src/libcore/send_map.rs index 5f440aa6d37..812b138097a 100644 --- a/src/libcore/send_map.rs +++ b/src/libcore/send_map.rs @@ -23,30 +23,10 @@ use hash::Hash; use prelude::*; use to_bytes::IterBytes; -pub trait SendMap { - // FIXME(#3148) ^^^^ once find_ref() works, we can drop V:copy - - fn insert(&mut self, k: K, +v: V) -> bool; - fn remove(&mut self, k: &K) -> bool; - fn pop(&mut self, k: &K) -> Option; - fn swap(&mut self, k: K, +v: V) -> Option; - fn consume(&mut self, f: fn(K, V)); - pure fn len(&const self) -> uint; - pure fn is_empty(&const self) -> bool; - pure fn contains_key(&const self, k: &K) -> bool; - pure fn each(&self, blk: fn(k: &K, v: &V) -> bool); - pure fn each_key_ref(&self, blk: fn(k: &K) -> bool); - pure fn each_value_ref(&self, blk: fn(v: &V) -> bool); - pure fn find(&const self, k: &K) -> Option; - pure fn get(&const self, k: &K) -> V; - pure fn find_ref(&self, k: &K) -> Option<&self/V>; - pure fn get_ref(&self, k: &K) -> &self/V; -} - /// Open addressing with linear probing. pub mod linear { use iter::BaseIter; - use container::{Mutable, Set}; + use container::{Mutable, Map, Set}; use cmp::Eq; use cmp; use hash::Hash; @@ -287,7 +267,34 @@ pub mod linear { } } - impl LinearMap { + impl LinearMap: Map { + pure fn contains_key(&self, k: &K) -> bool { + match self.bucket_for_key(self.buckets, k) { + FoundEntry(_) => {true} + TableFull | FoundHole(_) => {false} + } + } + + pure fn each(&self, blk: fn(k: &K, v: &V) -> bool) { + for vec::each(self.buckets) |slot| { + let mut broke = false; + do slot.iter |bucket| { + if !blk(&bucket.key, &bucket.value) { + broke = true; // FIXME(#3064) just write "break;" + } + } + if broke { break; } + } + } + + pure fn each_key(&self, blk: fn(k: &K) -> bool) { + self.each(|k, _v| blk(k)) + } + + pure fn each_value(&self, blk: fn(v: &V) -> bool) { + self.each(|_k, v| blk(v)) + } + fn insert(&mut self, k: K, v: V) -> bool { if self.size >= self.resize_at { // n.b.: We could also do this after searching, so @@ -309,7 +316,9 @@ pub mod linear { None => false, } } + } + impl LinearMap { fn pop(&mut self, k: &K) -> Option { let hash = k.hash_keyed(self.k0, self.k1) as uint; self.pop_internal(hash, k) @@ -363,14 +372,6 @@ pub mod linear { self.len() == 0 } - pure fn contains_key(&const self, - k: &K) -> bool { - match self.bucket_for_key(self.buckets, k) { - FoundEntry(_) => {true} - TableFull | FoundHole(_) => {false} - } - } - pure fn find_ref(&self, k: &K) -> Option<&self/V> { match self.bucket_for_key(self.buckets, k) { FoundEntry(idx) => { @@ -397,26 +398,6 @@ pub mod linear { None => fail fmt!("No entry found for key: %?", k), } } - - pure fn each(&self, blk: fn(k: &K, v: &V) -> bool) { - for vec::each(self.buckets) |slot| { - let mut broke = false; - do slot.iter |bucket| { - if !blk(&bucket.key, &bucket.value) { - broke = true; // FIXME(#3064) just write "break;" - } - } - if broke { break; } - } - } - - pure fn each_key(&self, blk: fn(k: &K) -> bool) { - self.each(|k, _v| blk(k)) - } - - pure fn each_value(&self, blk: fn(v: &V) -> bool) { - self.each(|_k, v| blk(v)) - } } impl LinearMap { diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index 74a14b7903c..ff60d7d1c2b 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -14,7 +14,7 @@ #[forbid(deprecated_mode)]; -use core::container::{Mutable, Set}; +use core::container::{Mutable, Map, Set}; use core::cmp::{Eq, Ord}; use core::option::{Option, Some, None}; use core::prelude::*; @@ -75,6 +75,39 @@ impl TreeMap: Mutable { } } +impl TreeMap: Map { + /// Return true if the map contains a value for the specified key + pure fn contains_key(&self, key: &K) -> bool { + self.find(key).is_some() + } + + /// Visit all key-value pairs in order + pure fn each(&self, f: fn(&K, &V) -> bool) { each(&self.root, f) } + + /// Visit all keys in order + pure fn each_key(&self, f: fn(&K) -> bool) { self.each(|k, _| f(k)) } + + /// Visit all values in order + pure fn each_value(&self, f: fn(&V) -> bool) { self.each(|_, v| f(v)) } + + /// Insert a key-value pair into the map. An existing value for a + /// key is replaced by the new value. Return true if the key did + /// not already exist in the map. + fn insert(&mut self, key: K, value: V) -> bool { + let ret = insert(&mut self.root, key, value); + if ret { self.length += 1 } + ret + } + + /// Remove a key-value pair from the map. Return true if the key + /// was present in the map, otherwise false. + fn remove(&mut self, key: &K) -> bool { + let ret = remove(&mut self.root, key); + if ret { self.length -= 1 } + ret + } +} + impl TreeMap { /// Create an empty TreeMap static pure fn new() -> TreeMap { TreeMap{root: None, length: 0} } @@ -88,15 +121,6 @@ impl TreeMap { /// Return true if the map contains some elements pure fn is_not_empty(&self) -> bool { self.root.is_some() } - /// Visit all key-value pairs in order - pure fn each(&self, f: fn(&K, &V) -> bool) { each(&self.root, f) } - - /// Visit all keys in order - pure fn each_key(&self, f: fn(&K) -> bool) { self.each(|k, _| f(k)) } - - /// Visit all values in order - pure fn each_value(&self, f: fn(&V) -> bool) { self.each(|_, v| f(v)) } - /// Visit all key-value pairs in reverse order pure fn each_reverse(&self, f: fn(&K, &V) -> bool) { each_reverse(&self.root, f); @@ -112,11 +136,6 @@ impl TreeMap { self.each_reverse(|_, v| f(v)) } - /// Return true if the map contains a value for the specified key - pure fn contains_key(&self, key: &K) -> bool { - self.find(key).is_some() - } - /// Return the value corresponding to the key in the map pure fn find(&self, key: &K) -> Option<&self/V> { let mut current: &self/Option<~TreeNode> = &self.root; @@ -137,23 +156,6 @@ impl TreeMap { } } - /// Insert a key-value pair into the map. An existing value for a - /// key is replaced by the new value. Return true if the key did - /// not already exist in the map. - fn insert(&mut self, key: K, value: V) -> bool { - let ret = insert(&mut self.root, key, value); - if ret { self.length += 1 } - ret - } - - /// Remove a key-value pair from the map. Return true if the key - /// was present in the map, otherwise false. - fn remove(&mut self, key: &K) -> bool { - let ret = remove(&mut self.root, key); - if ret { self.length -= 1 } - ret - } - /// Get a lazy iterator over the key-value pairs in the map. /// Requires that it be frozen (immutable). pure fn iter(&self) -> TreeMapIterator/&self { From 6f4d86ed904ed7ae04edc4226a0a1c2d39067d57 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Mon, 21 Jan 2013 21:59:19 -0500 Subject: [PATCH 4/4] add a base Container trait --- src/libcore/container.rs | 10 +++++++++- src/libcore/send_map.rs | 26 +++++++++++--------------- src/libstd/priority_queue.rs | 16 +++++++++------- src/libstd/treemap.rs | 30 +++++++++++++++++------------- 4 files changed, 46 insertions(+), 36 deletions(-) diff --git a/src/libcore/container.rs b/src/libcore/container.rs index dd556aec45f..062416838cc 100644 --- a/src/libcore/container.rs +++ b/src/libcore/container.rs @@ -13,7 +13,15 @@ #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; -pub trait Mutable { +pub trait Container { + /// Return the number of elements in the container + pure fn len(&self) -> uint; + + /// Return true if the container contains no elements + pure fn is_empty(&self) -> bool; +} + +pub trait Mutable: Container { /// Clear the container, removing all values. fn clear(&mut self); } diff --git a/src/libcore/send_map.rs b/src/libcore/send_map.rs index 812b138097a..dc4e24c4f8a 100644 --- a/src/libcore/send_map.rs +++ b/src/libcore/send_map.rs @@ -26,7 +26,7 @@ use to_bytes::IterBytes; /// Open addressing with linear probing. pub mod linear { use iter::BaseIter; - use container::{Mutable, Map, Set}; + use container::{Container, Mutable, Map, Set}; use cmp::Eq; use cmp; use hash::Hash; @@ -258,6 +258,11 @@ pub mod linear { } } + impl LinearMap: Container { + pure fn len(&self) -> uint { self.size } + pure fn is_empty(&self) -> bool { self.len() == 0 } + } + impl LinearMap: Mutable { fn clear(&mut self) { for uint::range(0, self.buckets.len()) |idx| { @@ -364,14 +369,6 @@ pub mod linear { } } - pure fn len(&const self) -> uint { - self.size - } - - pure fn is_empty(&const self) -> bool { - self.len() == 0 - } - pure fn find_ref(&self, k: &K) -> Option<&self/V> { match self.bucket_for_key(self.buckets, k) { FoundEntry(idx) => { @@ -464,6 +461,11 @@ pub mod linear { } } + impl LinearSet: Container { + pure fn len(&self) -> uint { self.map.len() } + pure fn is_empty(&self) -> bool { self.map.is_empty() } + } + impl LinearSet: Mutable { fn clear(&mut self) { self.map.clear() } } @@ -486,12 +488,6 @@ pub mod linear { impl LinearSet { /// Create an empty LinearSet static fn new() -> LinearSet { LinearSet{map: LinearMap()} } - - /// Return the number of elements in the set - pure fn len(&self) -> uint { self.map.len() } - - /// Return true if the set contains no elements - pure fn is_empty(&self) -> bool { self.map.is_empty() } } } diff --git a/src/libstd/priority_queue.rs b/src/libstd/priority_queue.rs index 0ff40b6421a..ee78fafb60b 100644 --- a/src/libstd/priority_queue.rs +++ b/src/libstd/priority_queue.rs @@ -10,7 +10,7 @@ //! A priority queue implemented with a binary heap -use core::container::Mutable; +use core::container::{Container, Mutable}; use core::cmp::Ord; use core::prelude::*; use core::ptr::addr_of; @@ -25,6 +25,14 @@ pub struct PriorityQueue { priv data: ~[T], } +impl PriorityQueue: Container { + /// Returns the length of the queue + pure fn len(&self) -> uint { self.data.len() } + + /// Returns true if a queue contains no elements + pure fn is_empty(&self) -> bool { self.data.is_empty() } +} + impl PriorityQueue: Mutable { /// Drop all items from the queue fn clear(&mut self) { self.data.truncate(0) } @@ -39,12 +47,6 @@ impl PriorityQueue { if self.is_empty() { None } else { Some(self.top()) } } - /// Returns the length of the queue - pure fn len(&self) -> uint { self.data.len() } - - /// Returns true if a queue contains no elements - pure fn is_empty(&self) -> bool { self.data.is_empty() } - /// Returns true if a queue contains some elements pure fn is_not_empty(&self) -> bool { self.data.is_not_empty() } diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index ff60d7d1c2b..0bb8738773c 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -14,7 +14,7 @@ #[forbid(deprecated_mode)]; -use core::container::{Mutable, Map, Set}; +use core::container::{Container, Mutable, Map, Set}; use core::cmp::{Eq, Ord}; use core::option::{Option, Some, None}; use core::prelude::*; @@ -67,6 +67,14 @@ impl TreeMap: Eq { pure fn ne(&self, other: &TreeMap) -> bool { !self.eq(other) } } +impl TreeMap: Container { + /// Return the number of elements in the map + pure fn len(&self) -> uint { self.length } + + /// Return true if the map contains no elements + pure fn is_empty(&self) -> bool { self.root.is_none() } +} + impl TreeMap: Mutable { /// Clear the map, removing all key-value pairs. fn clear(&mut self) { @@ -112,12 +120,6 @@ impl TreeMap { /// Create an empty TreeMap static pure fn new() -> TreeMap { TreeMap{root: None, length: 0} } - /// Return the number of elements in the map - pure fn len(&self) -> uint { self.length } - - /// Return true if the map contains no elements - pure fn is_empty(&self) -> bool { self.root.is_none() } - /// Return true if the map contains some elements pure fn is_not_empty(&self) -> bool { self.root.is_some() } @@ -206,6 +208,14 @@ impl TreeSet: Eq { pure fn ne(&self, other: &TreeSet) -> bool { self.map != other.map } } +impl TreeSet: Container { + /// Return the number of elements in the map + pure fn len(&self) -> uint { self.map.len() } + + /// Return true if the map contains no elements + pure fn is_empty(&self) -> bool { self.map.is_empty() } +} + impl TreeSet: Mutable { /// Clear the set, removing all values. fn clear(&mut self) { self.map.clear() } @@ -230,12 +240,6 @@ impl TreeSet { /// Create an empty TreeSet static pure fn new() -> TreeSet { TreeSet{map: TreeMap::new()} } - /// Return the number of elements in the set - pure fn len(&self) -> uint { self.map.len() } - - /// Return true if the set contains no elements - pure fn is_empty(&self) -> bool { self.map.is_empty() } - /// Return true if the set contains some elements pure fn is_not_empty(&self) -> bool { self.map.is_not_empty() }