Skip to content

Commit

Permalink
auto merge of #7373 : thestinger/rust/iterator, r=huonw
Browse files Browse the repository at this point in the history
  • Loading branch information
bors committed Jun 25, 2013
2 parents 4967bd0 + e44e33d commit efd1438
Show file tree
Hide file tree
Showing 58 changed files with 259 additions and 382 deletions.
57 changes: 44 additions & 13 deletions doc/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -1552,13 +1552,6 @@ fn each(v: &[int], op: &fn(v: &int)) {
}
~~~~

As an aside, the reason we pass in a *pointer* to an integer rather
than the integer itself is that this is how the actual `each()`
function for vectors works. `vec::each` though is a
[generic](#generics) function, so must be efficient to use for all
types. Passing the elements by pointer avoids copying potentially
large objects.

As a caller, if we use a closure to provide the final operator
argument, we can write it in a way that has a pleasant, block-like
structure.
Expand Down Expand Up @@ -1616,6 +1609,9 @@ To enable `debug!` logging, set the RUST_LOG environment variable to the name of

## For loops

> ***Note:*** The closure-based protocol used `for` loop is on the way out. The `for` loop will
> use iterator objects in the future instead.
The most common way to express iteration in Rust is with a `for`
loop. Like `do`, `for` is a nice syntax for describing control flow
with closures. Additionally, within a `for` loop, `break`, `loop`,
Expand All @@ -1640,7 +1636,16 @@ fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
And using this function to iterate over a vector:

~~~~
# use each = std::vec::each;
# fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
# let mut n = 0;
# while n < v.len() {
# if !op(&v[n]) {
# return false;
# }
# n += 1;
# }
# return true;
# }
each([2, 4, 8, 5, 16], |n| {
if *n % 2 != 0 {
println("found odd number!");
Expand All @@ -1656,7 +1661,16 @@ out of the loop, you just write `break`. To skip ahead
to the next iteration, write `loop`.

~~~~
# use each = std::vec::each;
# fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
# let mut n = 0;
# while n < v.len() {
# if !op(&v[n]) {
# return false;
# }
# n += 1;
# }
# return true;
# }
for each([2, 4, 8, 5, 16]) |n| {
if *n % 2 != 0 {
println("found odd number!");
Expand All @@ -1671,7 +1685,16 @@ normally allowed in closures, in a block that appears as the body of a
the enclosing function, not just the loop body.

~~~~
# use each = std::vec::each;
# fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
# let mut n = 0;
# while n < v.len() {
# if !op(&v[n]) {
# return false;
# }
# n += 1;
# }
# return true;
# }
fn contains(v: &[int], elt: int) -> bool {
for each(v) |x| {
if (*x == elt) { return true; }
Expand All @@ -1686,7 +1709,16 @@ In these situations it can be convenient to lean on Rust's
argument patterns to bind `x` to the actual value, not the pointer.

~~~~
# use each = std::vec::each;
# fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
# let mut n = 0;
# while n < v.len() {
# if !op(&v[n]) {
# return false;
# }
# n += 1;
# }
# return true;
# }
# fn contains(v: &[int], elt: int) -> bool {
for each(v) |&x| {
if (x == elt) { return true; }
Expand Down Expand Up @@ -1841,10 +1873,9 @@ vector consisting of the result of applying `function` to each element
of `vector`:

~~~~
# use std::vec;
fn map<T, U>(vector: &[T], function: &fn(v: &T) -> U) -> ~[U] {
let mut accumulator = ~[];
for vec::each(vector) |element| {
for vector.iter().advance |element| {
accumulator.push(function(element));
}
return accumulator;
Expand Down
2 changes: 1 addition & 1 deletion src/compiletest/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ fn compose_and_run_compiler(
let extra_link_args = ~[~"-L",
aux_output_dir_name(config, testfile).to_str()];

for vec::each(props.aux_builds) |rel_ab| {
for props.aux_builds.iter().advance |rel_ab| {
let abs_ab = config.aux_base.push_rel(&Path(*rel_ab));
let aux_args =
make_compile_args(config, props, ~[~"--lib"] + extra_link_args,
Expand Down
11 changes: 7 additions & 4 deletions src/libextra/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ mod tests {
use core::cell::Cell;
use core::comm;
use core::task;
use core::uint;

#[test]
fn manually_share_arc() {
Expand Down Expand Up @@ -790,18 +791,20 @@ mod tests {
}
assert_eq!(*state, 42);
*state = 31337;
// FIXME: #7372: hits type inference bug with iterators
// send to other readers
for vec::each(reader_convos) |x| {
match *x {
for uint::range(0, reader_convos.len()) |i| {
match reader_convos[i] {
(ref rc, _) => rc.send(()),
}
}
}
let read_mode = arc.downgrade(write_mode);
do (&read_mode).read |state| {
// FIXME: #7372: hits type inference bug with iterators
// complete handshake with other readers
for vec::each(reader_convos) |x| {
match *x {
for uint::range(0, reader_convos.len()) |i| {
match reader_convos[i] {
(_, ref rp) => rp.recv(),
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/libextra/getopts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,10 +418,11 @@ pub fn opts_str(mm: &Matches, names: &[~str]) -> ~str {
*/
pub fn opt_strs(mm: &Matches, nm: &str) -> ~[~str] {
let mut acc: ~[~str] = ~[];
for vec::each(opt_vals(mm, nm)) |v| {
let r = opt_vals(mm, nm);
for r.iter().advance |v| {
match *v { Val(ref s) => acc.push(copy *s), _ => () }
}
return acc;
acc
}

/// Returns the string argument supplied to a matching option or none
Expand Down
8 changes: 4 additions & 4 deletions src/libextra/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@ impl Eq for Json {
&Object(ref d1) => {
if d0.len() == d1.len() {
let mut equal = true;
for d0.each |k, v0| {
for d0.iter().advance |(k, v0)| {
match d1.find(k) {
Some(v1) if v0 == v1 => { },
_ => { equal = false; break }
Expand Down Expand Up @@ -1186,12 +1186,12 @@ impl Ord for Json {
let mut d1_flat = ~[];

// FIXME #4430: this is horribly inefficient...
for d0.each |k, v| {
for d0.iter().advance |(k, v)| {
d0_flat.push((@copy *k, @copy *v));
}
d0_flat.qsort();

for d1.each |k, v| {
for d1.iter().advance |(k, v)| {
d1_flat.push((@copy *k, @copy *v));
}
d1_flat.qsort();
Expand Down Expand Up @@ -1326,7 +1326,7 @@ impl<A:ToJson> ToJson for ~[A] {
impl<A:ToJson + Copy> ToJson for HashMap<~str, A> {
fn to_json(&self) -> Json {
let mut d = HashMap::new();
for self.each |key, value| {
for self.iter().advance |(key, value)| {
d.insert(copy *key, value.to_json());
}
Object(~d)
Expand Down
2 changes: 1 addition & 1 deletion src/libextra/net_url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ pub fn encode_form_urlencoded(m: &HashMap<~str, ~[~str]>) -> ~str {
let mut out = ~"";
let mut first = true;

for m.each |key, values| {
for m.iter().advance |(key, values)| {
let key = encode_plus(*key);

for values.iter().advance |value| {
Expand Down
4 changes: 2 additions & 2 deletions src/libextra/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ impl<
fn encode(&self, e: &mut E) {
do e.emit_map(self.len()) |e| {
let mut i = 0;
for self.each |key, val| {
for self.iter().advance |(key, val)| {
e.emit_map_elt_key(i, |e| key.encode(e));
e.emit_map_elt_val(i, |e| val.encode(e));
i += 1;
Expand Down Expand Up @@ -744,7 +744,7 @@ impl<
fn encode(&self, s: &mut S) {
do s.emit_seq(self.len()) |s| {
let mut i = 0;
for self.each |e| {
for self.iter().advance |e| {
s.emit_seq_elt(i, |s| e.encode(s));
i += 1;
}
Expand Down
64 changes: 32 additions & 32 deletions src/libextra/smallintmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,38 +56,6 @@ impl<V> Map<uint, V> for SmallIntMap<V> {
self.find(key).is_some()
}

/// Visit all key-value pairs in order
fn each<'a>(&'a self, it: &fn(&uint, &'a V) -> bool) -> bool {
for uint::range(0, self.v.len()) |i| {
match self.v[i] {
Some(ref elt) => if !it(&i, elt) { return false; },
None => ()
}
}
return true;
}

/// Visit all keys in order
fn each_key(&self, blk: &fn(key: &uint) -> bool) -> bool {
self.each(|k, _| blk(k))
}

/// Visit all values in order
fn each_value<'a>(&'a self, blk: &fn(value: &'a V) -> bool) -> bool {
self.each(|_, v| blk(v))
}

/// Iterate over the map and mutate the contained values
fn mutate_values(&mut self, it: &fn(&uint, &mut V) -> bool) -> bool {
for uint::range(0, self.v.len()) |i| {
match self.v[i] {
Some(ref mut elt) => if !it(&i, elt) { return false; },
None => ()
}
}
return true;
}

/// Return a reference to the value corresponding to the key
fn find<'a>(&'a self, key: &uint) -> Option<&'a V> {
if *key < self.v.len() {
Expand Down Expand Up @@ -156,6 +124,38 @@ impl<V> SmallIntMap<V> {
/// Create an empty SmallIntMap
pub fn new() -> SmallIntMap<V> { SmallIntMap{v: ~[]} }

/// Visit all key-value pairs in order
pub fn each<'a>(&'a self, it: &fn(&uint, &'a V) -> bool) -> bool {
for uint::range(0, self.v.len()) |i| {
match self.v[i] {
Some(ref elt) => if !it(&i, elt) { return false; },
None => ()
}
}
return true;
}

/// Visit all keys in order
pub fn each_key(&self, blk: &fn(key: &uint) -> bool) -> bool {
self.each(|k, _| blk(k))
}

/// Visit all values in order
pub fn each_value<'a>(&'a self, blk: &fn(value: &'a V) -> bool) -> bool {
self.each(|_, v| blk(v))
}

/// Iterate over the map and mutate the contained values
pub fn mutate_values(&mut self, it: &fn(&uint, &mut V) -> bool) -> bool {
for uint::range(0, self.v.len()) |i| {
match self.v[i] {
Some(ref mut elt) => if !it(&i, elt) { return false; },
None => ()
}
}
return true;
}

/// Visit all key-value pairs in reverse order
pub fn each_reverse<'a>(&'a self, it: &fn(uint, &'a V) -> bool) -> bool {
for uint::range_rev(self.v.len(), 0) |i| {
Expand Down
3 changes: 2 additions & 1 deletion src/libextra/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,7 +1094,8 @@ mod tests {
};
assert!(result.is_err());
// child task must have finished by the time try returns
for vec::each(p.recv()) |p| { p.recv(); } // wait on all its siblings
let r = p.recv();
for r.iter().advance |p| { p.recv(); } // wait on all its siblings
do m.lock_cond |cond| {
let woken = cond.broadcast();
assert_eq!(woken, 0);
Expand Down
40 changes: 20 additions & 20 deletions src/libextra/treemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,26 +107,6 @@ impl<K: TotalOrd, V> Map<K, V> for TreeMap<K, V> {
self.find(key).is_some()
}

/// Visit all key-value pairs in order
fn each<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) -> bool {
each(&self.root, f)
}

/// Visit all keys in order
fn each_key(&self, f: &fn(&K) -> bool) -> bool {
self.each(|k, _| f(k))
}

/// Visit all values in order
fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool) -> bool {
self.each(|_, v| f(v))
}

/// Iterate over the map and mutate the contained values
fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool) -> bool {
mutate_values(&mut self.root, f)
}

/// Return a reference to the value corresponding to the key
fn find<'a>(&'a self, key: &K) -> Option<&'a V> {
let mut current: &'a Option<~TreeNode<K, V>> = &self.root;
Expand Down Expand Up @@ -184,6 +164,26 @@ impl<K: TotalOrd, V> TreeMap<K, V> {
/// Create an empty TreeMap
pub fn new() -> TreeMap<K, V> { TreeMap{root: None, length: 0} }

/// Visit all key-value pairs in order
pub fn each<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) -> bool {
each(&self.root, f)
}

/// Visit all keys in order
pub fn each_key(&self, f: &fn(&K) -> bool) -> bool {
self.each(|k, _| f(k))
}

/// Visit all values in order
pub fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool) -> bool {
self.each(|_, v| f(v))
}

/// Iterate over the map and mutate the contained values
pub fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool) -> bool {
mutate_values(&mut self.root, f)
}

/// Visit all key-value pairs in reverse order
pub fn each_reverse<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) -> bool {
each_reverse(&self.root, f)
Expand Down
4 changes: 2 additions & 2 deletions src/libextra/workcache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl WorkMap {
impl<S:Encoder> Encodable<S> for WorkMap {
fn encode(&self, s: &mut S) {
let mut d = ~[];
for self.each |k, v| {
for self.iter().advance |(k, v)| {
d.push((copy *k, copy *v))
}
sort::tim_sort(d);
Expand Down Expand Up @@ -320,7 +320,7 @@ impl TPrep for Prep {
}

fn all_fresh(&self, cat: &str, map: &WorkMap) -> bool {
for map.each |k, v| {
for map.iter().advance |(k, v)| {
if ! self.is_fresh(cat, k.kind, k.name, *v) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/metadata/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub fn have_crate_data(cstore: &CStore, cnum: ast::crate_num) -> bool {

pub fn iter_crate_data(cstore: &CStore,
i: &fn(ast::crate_num, @crate_metadata)) {
for cstore.metas.each |&k, &v| {
for cstore.metas.iter().advance |(&k, &v)| {
i(k, v);
}
}
Expand Down
Loading

0 comments on commit efd1438

Please sign in to comment.