auto merge of #4835 : thestinger/rust/iterator, r=graydon

This adds a `BaseIter` impl to `PriorityQueue`, `TreeMap`, `LinearMap` and `SmallIntMap`, and introduces a `ReverseIter` trait + implementations for `TreeMap`, `TreeSet` and `SmallIntMap`.
This commit is contained in:
bors 2013-02-07 21:37:59 -08:00
commit 9b4fa844d8
12 changed files with 133 additions and 87 deletions

View File

@ -495,7 +495,7 @@ pub fn try_parse_sources(filename: &Path,
let c = io::read_whole_file_str(filename);
match json::from_str(c.get()) {
Ok(json::Object(j)) => {
for j.each |k, v| {
for j.each |&(k, v)| {
sources.insert(copy *k, parse_source(*k, v));
debug!("source: %s", *k);
}

View File

@ -29,9 +29,6 @@ pub trait Map<K, V>: 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);

View File

@ -235,6 +235,23 @@ pub mod linear {
}
}
impl <K: Hash IterBytes Eq, V> LinearMap<K, V>: BaseIter<(&K, &V)> {
/// Visit all key-value pairs
pure fn each(&self, blk: fn(&(&self/K, &self/V)) -> bool) {
for uint::range(0, self.buckets.len()) |i| {
let mut broke = false;
do self.buckets[i].map |bucket| {
if !blk(&(&bucket.key, &bucket.value)) {
broke = true; // FIXME(#3064) just write "break;"
}
};
if broke { break; }
}
}
pure fn size_hint(&self) -> Option<uint> { Some(self.len()) }
}
impl <K: Hash IterBytes Eq, V> LinearMap<K, V>: Container {
/// Return the number of elements in the map
pure fn len(&self) -> uint { self.size }
@ -262,27 +279,14 @@ pub mod linear {
}
}
/// Visit all key-value pairs
pure fn each(&self, blk: fn(k: &K, v: &V) -> bool) {
for self.buckets.each |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; }
}
}
/// Visit all keys
pure fn each_key(&self, blk: fn(k: &K) -> bool) {
self.each(|k, _| blk(k))
self.each(|&(k, _)| blk(k))
}
/// Visit all values
pure fn each_value(&self, blk: fn(v: &V) -> bool) {
self.each(|_, v| blk(v))
self.each(|&(_, v)| blk(v))
}
/// Return the value corresponding to the key in the map
@ -388,7 +392,7 @@ pub mod linear {
pure fn eq(&self, other: &LinearMap<K, V>) -> bool {
if self.len() != other.len() { return false; }
for self.each |key, value| {
for self.each |&(key, value)| {
match other.find(key) {
None => return false,
Some(v) => if value != v { return false },
@ -603,7 +607,7 @@ mod test_map {
assert m.insert(i, i*2);
}
let mut observed = 0;
for m.each |k, v| {
for m.each |&(k, v)| {
assert *v == *k * 2;
observed |= (1 << *k);
}

View File

@ -27,6 +27,10 @@ pub trait BaseIter<A> {
pure fn size_hint(&self) -> Option<uint>;
}
pub trait ReverseIter<A>: BaseIter<A> {
pure fn each_reverse(&self, blk: fn(&A) -> bool);
}
pub trait ExtendedIter<A> {
pure fn eachi(&self, blk: fn(uint, v: &A) -> bool);
pure fn all(&self, blk: fn(&A) -> bool) -> bool;

View File

@ -102,7 +102,7 @@ pub pure fn get_ref<T>(opt: &r/Option<T>) -> &r/T {
}
#[inline(always)]
pub pure fn map<T, U>(opt: &Option<T>, f: fn(x: &T) -> U) -> Option<U> {
pub pure fn map<T, U>(opt: &r/Option<T>, f: fn(x: &r/T) -> U) -> Option<U> {
//! Maps a `some` value by reference from one type to another
match *opt { Some(ref x) => Some(f(x)), None => None }
@ -193,8 +193,8 @@ pub pure fn get_or_default<T: Copy>(opt: Option<T>, def: T) -> T {
}
#[inline(always)]
pub pure fn map_default<T, U>(opt: &Option<T>, def: U,
f: fn(x: &T) -> U) -> U {
pub pure fn map_default<T, U>(opt: &r/Option<T>, def: U,
f: fn(&r/T) -> U) -> U {
//! Applies a function to the contained value or returns a default
match *opt { None => move def, Some(ref t) => f(t) }
@ -273,7 +273,7 @@ impl<T> Option<T> {
/// Maps a `some` value from one type to another by reference
#[inline(always)]
pure fn map<U>(&self, f: fn(x: &T) -> U) -> Option<U> { map(self, f) }
pure fn map<U>(&self, f: fn(&self/T) -> U) -> Option<U> { map(self, f) }
/// As `map`, but consumes the option and gives `f` ownership to avoid
/// copying.
@ -284,7 +284,7 @@ impl<T> Option<T> {
/// Applies a function to the contained value or returns a default
#[inline(always)]
pure fn map_default<U>(&self, def: U, f: fn(x: &T) -> U) -> U {
pure fn map_default<U>(&self, def: U, f: fn(&self/T) -> U) -> U {
map_default(self, move def, f)
}

View File

@ -302,7 +302,7 @@ pub impl<S: serialize::Encoder> Json: serialize::Encodable<S> {
Object(ref v) => {
do s.emit_rec || {
let mut idx = 0;
for v.each |key, value| {
for v.each |&(key, value)| {
do s.emit_field(*key, idx) {
value.encode(s);
}
@ -936,7 +936,7 @@ impl Json : Eq {
&Object(ref d1) => {
if d0.len() == d1.len() {
let mut equal = true;
for d0.each |k, v0| {
for d0.each |&(k, v0)| {
match d1.find(k) {
Some(v1) if v0 == v1 => { },
_ => { equal = false; break }
@ -1000,12 +1000,12 @@ impl Json : Ord {
let mut d1_flat = ~[];
// FIXME #4430: this is horribly inefficient...
for d0.each |k, v| {
for d0.each |&(k, v)| {
d0_flat.push((@copy *k, @copy *v));
}
d0_flat.qsort();
for d1.each |k, v| {
for d1.each |&(k, v)| {
d1_flat.push((@copy *k, @copy *v));
}
d1_flat.qsort();
@ -1146,7 +1146,7 @@ impl <A: ToJson> ~[A]: ToJson {
impl <A: ToJson Copy> LinearMap<~str, A>: ToJson {
fn to_json() -> Json {
let mut d = LinearMap::new();
for self.each() |key, value| {
for self.each |&(key, value)| {
d.insert(copy *key, value.to_json());
}
Object(~d)

View File

@ -219,10 +219,10 @@ pub fn encode_form_urlencoded(m: &LinearMap<~str, ~[~str]>) -> ~str {
let mut out = ~"";
let mut first = true;
for m.each |key, values| {
for m.each |&(key, values)| {
let key = encode_plus(*key);
for (*values).each |value| {
for values.each |value| {
if first {
first = false;
} else {

View File

@ -12,6 +12,7 @@
use core::container::{Container, Mutable};
use core::cmp::Ord;
use core::iter::BaseIter;
use core::prelude::*;
use core::ptr::addr_of;
use core::vec;
@ -26,6 +27,14 @@ pub struct PriorityQueue<T> {
priv data: ~[T],
}
impl <T: Ord> PriorityQueue<T>: BaseIter<T> {
/// Visit all values in the underlying vector.
///
/// The values are **not** visited in order.
pure fn each(&self, f: fn(&T) -> bool) { self.data.each(f) }
pure fn size_hint(&self) -> Option<uint> { self.data.size_hint() }
}
impl <T: Ord> PriorityQueue<T>: Container {
/// Returns the length of the queue
pure fn len(&self) -> uint { self.data.len() }

View File

@ -14,6 +14,7 @@
*/
use core::container::{Container, Mutable, Map, Set};
use core::iter::{BaseIter, ReverseIter};
use core::option::{Some, None};
use core::prelude::*;
@ -21,6 +22,32 @@ pub struct SmallIntMap<T> {
priv v: ~[Option<T>],
}
impl<V> SmallIntMap<V>: BaseIter<(uint, &V)> {
/// Visit all key-value pairs in order
pure fn each(&self, it: fn(&(uint, &self/V)) -> bool) {
for uint::range(0, self.v.len()) |i| {
match self.v[i] {
Some(ref elt) => if !it(&(i, elt)) { break },
None => ()
}
}
}
pure fn size_hint(&self) -> Option<uint> { Some(self.len()) }
}
impl<V> SmallIntMap<V>: ReverseIter<(uint, &V)> {
/// Visit all key-value pairs in reverse order
pure fn each_reverse(&self, it: fn(&(uint, &self/V)) -> bool) {
for uint::range_rev(self.v.len(), 0) |i| {
match self.v[i - 1] {
Some(ref elt) => if !it(&(i - 1, elt)) { break },
None => ()
}
}
}
}
impl<V> SmallIntMap<V>: Container {
/// Return the number of elements in the map
pure fn len(&self) -> uint {
@ -48,24 +75,14 @@ impl<V> SmallIntMap<V>: Map<uint, V> {
self.find(key).is_some()
}
/// Visit all key-value pairs
pure fn each(&self, it: fn(key: &uint, value: &V) -> bool) {
for uint::range(0, self.v.len()) |i| {
match self.v[i] {
Some(ref elt) => if !it(&i, elt) { break },
None => ()
}
}
}
/// Visit all keys
/// Visit all keys in order
pure fn each_key(&self, blk: fn(key: &uint) -> bool) {
self.each(|k, _| blk(k))
self.each(|&(k, _)| blk(&k))
}
/// Visit all values
/// Visit all values in order
pure fn each_value(&self, blk: fn(value: &V) -> bool) {
self.each(|_, v| blk(v))
self.each(|&(_, v)| blk(v))
}
/// Return the value corresponding to the key in the map

View File

@ -14,6 +14,7 @@
use core::container::{Container, Mutable, Map, Set};
use core::cmp::{Eq, Ord};
use core::iter::{BaseIter, ReverseIter};
use core::option::{Option, Some, None};
use core::prelude::*;
@ -103,6 +104,21 @@ impl <K: Ord, V> TreeMap<K, V>: Ord {
}
}
impl <K: Ord, V> TreeMap<K, V>: BaseIter<(&K, &V)> {
/// Visit all key-value pairs in order
pure fn each(&self, f: fn(&(&self/K, &self/V)) -> bool) {
each(&self.root, f)
}
pure fn size_hint(&self) -> Option<uint> { Some(self.len()) }
}
impl <K: Ord, V> TreeMap<K, V>: ReverseIter<(&K, &V)> {
/// Visit all key-value pairs in reverse order
pure fn each_reverse(&self, f: fn(&(&self/K, &self/V)) -> bool) {
each_reverse(&self.root, f);
}
}
impl <K: Ord, V> TreeMap<K, V>: Container {
/// Return the number of elements in the map
pure fn len(&self) -> uint { self.length }
@ -125,14 +141,11 @@ impl <K: Ord, V> TreeMap<K, V>: Map<K, V> {
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)) }
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)) }
pure fn each_value(&self, f: fn(&V) -> bool) { self.each(|&(_, v)| f(v)) }
/// Return the value corresponding to the key in the map
pure fn find(&self, key: &K) -> Option<&self/V> {
@ -175,19 +188,14 @@ impl <K: Ord, V> TreeMap<K, V> {
/// Create an empty TreeMap
static pure fn new() -> TreeMap<K, V> { TreeMap{root: None, length: 0} }
/// Visit all key-value pairs in reverse order
pure fn each_reverse(&self, f: fn(&K, &V) -> bool) {
each_reverse(&self.root, f);
}
/// Visit all keys in reverse order
pure fn each_key_reverse(&self, f: fn(&K) -> bool) {
self.each_reverse(|k, _| f(k))
self.each_reverse(|&(k, _)| f(k))
}
/// Visit all values in reverse order
pure fn each_value_reverse(&self, f: fn(&V) -> bool) {
self.each_reverse(|_, v| f(v))
self.each_reverse(|&(_, v)| f(v))
}
/// Get a lazy iterator over the key-value pairs in the map.
@ -238,12 +246,19 @@ pub struct TreeSet<T> {
priv map: TreeMap<T, ()>
}
impl <T: Ord> TreeSet<T>: iter::BaseIter<T> {
impl <T: Ord> TreeSet<T>: BaseIter<T> {
/// Visit all values in order
pure fn each(&self, f: fn(&T) -> bool) { self.map.each_key(f) }
pure fn size_hint(&self) -> Option<uint> { Some(self.len()) }
}
impl <T: Ord> TreeSet<T>: ReverseIter<T> {
/// Visit all values in reverse order
pure fn each_reverse(&self, f: fn(&T) -> bool) {
self.map.each_key_reverse(f)
}
}
impl <T: Eq Ord> TreeSet<T>: Eq {
pure fn eq(&self, other: &TreeSet<T>) -> bool { self.map == other.map }
pure fn ne(&self, other: &TreeSet<T>) -> bool { self.map != other.map }
@ -499,11 +514,6 @@ impl <T: Ord> TreeSet<T> {
/// Create an empty TreeSet
static pure fn new() -> TreeSet<T> { TreeSet{map: TreeMap::new()} }
/// Visit all values in reverse order
pure fn each_reverse(&self, f: fn(&T) -> bool) {
self.map.each_key_reverse(f)
}
/// Get a lazy iterator over the values in the set.
/// Requires that it be frozen (immutable).
pure fn iter(&self) -> TreeSetIterator/&self<T> {
@ -549,19 +559,19 @@ impl <K: Ord, V> TreeNode<K, V> {
}
}
pure fn each<K: Ord, V>(node: &Option<~TreeNode<K, V>>,
f: fn(&K, &V) -> bool) {
pure fn each<K: Ord, V>(node: &r/Option<~TreeNode<K, V>>,
f: fn(&(&r/K, &r/V)) -> bool) {
do node.map |x| {
each(&x.left, f);
if f(&x.key, &x.value) { each(&x.right, f) }
if f(&(&x.key, &x.value)) { each(&x.right, f) }
};
}
pure fn each_reverse<K: Ord, V>(node: &Option<~TreeNode<K, V>>,
f: fn(&K, &V) -> bool) {
pure fn each_reverse<K: Ord, V>(node: &r/Option<~TreeNode<K, V>>,
f: fn(&(&r/K, &r/V)) -> bool) {
do node.map |x| {
each_reverse(&x.right, f);
if f(&x.key, &x.value) { each_reverse(&x.left, f) }
if f(&(&x.key, &x.value)) { each_reverse(&x.left, f) }
};
}
@ -754,7 +764,7 @@ mod test_treemap {
let &(k, v) = x;
assert map.find(&k).unwrap() == &v
}
for map.each |map_k, map_v| {
for map.each |&(map_k, map_v)| {
let mut found = false;
for ctrl.each |x| {
let &(ctrl_k, ctrl_v) = x;
@ -868,7 +878,7 @@ mod test_treemap {
assert m.insert(1, 2);
let mut n = 0;
for m.each |k, v| {
for m.each |&(k, v)| {
assert *k == n;
assert *v == n * 2;
n += 1;
@ -886,7 +896,7 @@ mod test_treemap {
assert m.insert(1, 2);
let mut n = 4;
for m.each_reverse |k, v| {
for m.each_reverse |&(k, v)| {
assert *k == n;
assert *v == n * 2;
n -= 1;

View File

@ -142,7 +142,7 @@ type WorkMap = LinearMap<WorkKey, ~str>;
pub impl<S: Encoder> WorkMap: Encodable<S> {
fn encode(&self, s: &S) {
let d = dvec::DVec();
for self.each |k, v| {
for self.each |&(k, v)| {
d.push((copy *k, copy *v))
}
let mut v = d.get();
@ -155,7 +155,7 @@ pub impl<D: Decoder> WorkMap: Decodable<D> {
static fn decode(&self, d: &D) -> WorkMap {
let v : ~[(WorkKey,~str)] = Decodable::decode(d);
let mut w = LinearMap::new();
for v.each |&(k,v)| {
for v.each |&(k, v)| {
w.insert(copy k, copy v);
}
w
@ -312,7 +312,7 @@ impl @Mut<Prep> : TPrep {
}
fn all_fresh(&self, cat: &str, map: &WorkMap) -> bool {
for map.each |k,v| {
for map.each |&(k, v)| {
if ! self.is_fresh(cat, k.kind, k.name, *v) {
return false;
}

View File

@ -11,6 +11,7 @@
// xfail-fast
use core::container::{Container, Mutable, Map};
use core::iter::BaseIter;
enum cat_type { tuxedo, tabby, tortoiseshell }
@ -48,6 +49,18 @@ impl<T> cat<T> {
}
}
impl<T> cat<T>: BaseIter<(int, &T)> {
pure fn each(&self, f: fn(&(int, &self/T)) -> bool) {
let mut n = int::abs(self.meows);
while n > 0 {
if !f(&(n, &self.name)) { break; }
n -= 1;
}
}
pure fn size_hint(&self) -> Option<uint> { Some(self.len()) }
}
impl<T> cat<T>: Container {
pure fn len(&self) -> uint { self.meows as uint }
pure fn is_empty(&self) -> bool { self.meows == 0 }
@ -60,20 +73,12 @@ impl<T> cat<T>: Mutable {
impl<T> cat<T>: Map<int, T> {
pure fn contains_key(&self, k: &int) -> bool { *k <= self.meows }
pure fn each(&self, f: fn(v: &int, v: &T) -> bool) {
let mut n = int::abs(self.meows);
while n > 0 {
if !f(&n, &self.name) { break; }
n -= 1;
}
}
pure fn each_key(&self, f: fn(v: &int) -> bool) {
for self.each |k, _| { if !f(k) { break; } loop;};
for self.each |&(k, _)| { if !f(&k) { break; } loop;};
}
pure fn each_value(&self, f: fn(v: &T) -> bool) {
for self.each |_, v| { if !f(v) { break; } loop;};
for self.each |&(_, v)| { if !f(v) { break; } loop;};
}
fn insert(&mut self, k: int, _: T) -> bool {