Skip to content

some work on container iteration #4835

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
2 changes: 1 addition & 1 deletion src/libcargo/cargo.rc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
3 changes: 0 additions & 3 deletions src/libcore/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
38 changes: 21 additions & 17 deletions src/libcore/hashmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 4 additions & 0 deletions src/libcore/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 5 additions & 5 deletions src/libcore/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down Expand Up @@ -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) }
Expand Down Expand Up @@ -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.
Expand All @@ -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)
}

Expand Down
10 changes: 5 additions & 5 deletions src/libstd/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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 }
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/net_url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
9 changes: 9 additions & 0 deletions src/libstd/priority_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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() }
Expand Down
45 changes: 31 additions & 14 deletions src/libstd/smallintmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,40 @@
*/

use core::container::{Container, Mutable, Map, Set};
use core::iter::{BaseIter, ReverseIter};
use core::option::{Some, None};
use core::prelude::*;

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 {
Expand Down Expand Up @@ -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
Expand Down
Loading