From 6212729315be2ac80785ffcecfe0a80c9955c4cf Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Mon, 9 Sep 2013 04:46:32 +0200 Subject: [PATCH 1/5] std::vec: Change fn unzip to take an iterator argument Remove unzip_slice since it's redundant. Old unzip is equivalent to the `|x| unzip(x.move_iter())` --- src/librustdoc/config.rs | 2 +- src/libstd/select.rs | 8 ++++---- src/libstd/vec.rs | 36 +++++++++--------------------------- 3 files changed, 14 insertions(+), 32 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index dd43e22fc0c..e6d80e1443b 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -112,7 +112,7 @@ pub fn parse_config_( process_output: Process ) -> Result { let args = args.tail(); - let opts = vec::unzip(opts()).first(); + let opts = vec::unzip(opts().move_iter()).first(); match getopts::getopts(args, opts) { Ok(matches) => { if matches.free.len() == 1 { diff --git a/src/libstd/select.rs b/src/libstd/select.rs index 9f4fd8db788..695217a62f6 100644 --- a/src/libstd/select.rs +++ b/src/libstd/select.rs @@ -148,7 +148,7 @@ mod test { // Unfortunately this does not actually test the block_on early-break // codepath in select -- racing between the sender and the receiver in // separate tasks is necessary to get around the optimistic check. - let (ports, chans) = unzip(from_fn(num_ports, |_| oneshot::<()>())); + let (ports, chans) = unzip(range(0, num_ports).map(|_| oneshot::<()>())); let mut dead_chans = ~[]; let mut ports = ports; for (i, chan) in chans.move_iter().enumerate() { @@ -165,7 +165,7 @@ mod test { // Same thing with streams instead. // FIXME(#7971): This should be in a macro but borrowck isn't smart enough. - let (ports, chans) = unzip(from_fn(num_ports, |_| stream::<()>())); + let (ports, chans) = unzip(range(0, num_ports).map(|_| stream::<()>())); let mut dead_chans = ~[]; let mut ports = ports; for (i, chan) in chans.move_iter().enumerate() { @@ -209,7 +209,7 @@ mod test { // Sends 10 buffered packets, and uses select to retrieve them all. // Puts the port in a different spot in the vector each time. do run_in_newsched_task { - let (ports, _) = unzip(from_fn(10, |_| stream())); + let (ports, _) = unzip(range(0u, 10).map(|_| stream::())); let (port, chan) = stream(); do 10.times { chan.send(31337); } let mut ports = ports; @@ -327,7 +327,7 @@ mod test { let (p,c) = oneshot(); let c = Cell::new(c); do task::spawn { - let (dead_ps, dead_cs) = unzip(from_fn(5, |_| oneshot::<()>())); + let (dead_ps, dead_cs) = unzip(range(0u, 5).map(|_| oneshot::<()>())); let mut ports = dead_ps; select(ports); // should get killed; nothing should leak c.take().send(()); // must not happen diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 4cc5c4f14ff..10a0bf27836 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -389,37 +389,19 @@ impl<'self,T:Clone> VectorVector for &'self [&'self [T]] { } } -// FIXME: if issue #586 gets implemented, could have a postcondition -// saying the two result lists have the same length -- or, could -// return a nominal record with a constraint saying that, instead of -// returning a tuple (contingent on issue #869) /** - * Convert a vector of pairs into a pair of vectors, by reference. As unzip(). - */ -pub fn unzip_slice(v: &[(T, U)]) -> (~[T], ~[U]) { - let mut ts = ~[]; - let mut us = ~[]; - for p in v.iter() { - let (t, u) = (*p).clone(); - ts.push(t); - us.push(u); - } - (ts, us) -} - -/** - * Convert a vector of pairs into a pair of vectors. + * Convert an iterator of pairs into a pair of vectors. * * Returns a tuple containing two vectors where the i-th element of the first - * vector contains the first element of the i-th tuple of the input vector, + * vector contains the first element of the i-th tuple of the input iterator, * and the i-th element of the second vector contains the second element - * of the i-th tuple of the input vector. + * of the i-th tuple of the input iterator. */ -pub fn unzip(v: ~[(T, U)]) -> (~[T], ~[U]) { - let mut ts = ~[]; - let mut us = ~[]; - for p in v.move_iter() { - let (t, u) = p; +pub fn unzip>(mut iter: V) -> (~[T], ~[U]) { + let (lo, _) = iter.size_hint(); + let mut ts = with_capacity(lo); + let mut us = with_capacity(lo); + for (t, u) in iter { ts.push(t); us.push(u); } @@ -2891,7 +2873,7 @@ mod tests { fn test_zip_unzip() { let z1 = ~[(1, 4), (2, 5), (3, 6)]; - let (left, right) = unzip(z1); + let (left, right) = unzip(z1.iter().map(|&x| x)); assert_eq!((1, 4), (left[0], right[0])); assert_eq!((2, 5), (left[1], right[1])); From de9546a3f8c3153983a7b6069a9f2aee28f2e296 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Mon, 9 Sep 2013 01:29:07 +0200 Subject: [PATCH 2/5] std::vec: Replace each_permutation with a new Permutations iterator Introduce ElementSwaps and Permutations. ElementSwaps is an iterator that for a given sequence length yields the element swaps needed to visit each possible permutation of the sequence in turn. We use an algorithm that generates a sequence such that each permutation is only one swap apart. let mut v = [1, 2, 3]; for perm in v.permutations_iter() { // yields 1 2 3 | 1 3 2 | 3 1 2 | 3 2 1 | 2 3 1 | 2 1 3 } The `.permutations_iter()` yields clones of the input vector for each permutation. If a copyless traversal is needed, it can be constructed with `ElementSwaps`: for (a, b) in ElementSwaps::new(3) { // yields (2, 1), (1, 0), (2, 1) ... v.swap(a, b); // .. } --- src/libstd/vec.rs | 278 +++++++++++++++++++++++++++------------------- 1 file changed, 162 insertions(+), 116 deletions(-) diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 10a0bf27836..0a453d13714 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -408,56 +408,106 @@ pub fn unzip>(mut iter: V) -> (~[T], ~[U]) { (ts, us) } -/** - * Iterate over all permutations of vector `v`. - * - * Permutations are produced in lexicographic order with respect to the order - * of elements in `v` (so if `v` is sorted then the permutations are - * lexicographically sorted). - * - * The total number of permutations produced is `v.len()!`. If `v` contains - * repeated elements, then some permutations are repeated. - * - * See [Algorithms to generate - * permutations](http://en.wikipedia.org/wiki/Permutation). - * - * # Arguments - * - * * `values` - A vector of values from which the permutations are - * chosen - * - * * `fun` - The function to iterate over the combinations - */ -pub fn each_permutation(values: &[T], fun: &fn(perm : &[T]) -> bool) -> bool { - let length = values.len(); - let mut permutation = vec::from_fn(length, |i| values[i].clone()); - if length <= 1 { - fun(permutation); - return true; +/// An Iterator that yields the element swaps needed to produce +/// a sequence of all possible permutations for an indexed sequence of +/// elements. Each permutation is only a single swap apart. +/// +/// The Steinhaus–Johnson–Trotter algorithm is used. +/// +/// Generates even and odd permutations alternatingly. +/// +/// The last generated swap is always (0, 1), and it returns the +/// sequence to its initial order. +pub struct ElementSwaps { + priv sdir: ~[SizeDirection], + /// If true, emit the last swap that returns the sequence to initial state + priv emit_reset: bool, +} + +impl ElementSwaps { + /// Create an `ElementSwaps` iterator for a sequence of `length` elements + pub fn new(length: uint) -> ElementSwaps { + // Initialize `sdir` with a direction that position should move in + // (all negative at the beginning) and the `size` of the + // element (equal to the original index). + ElementSwaps{ + emit_reset: true, + sdir: range(0, length) + .map(|i| SizeDirection{ size: i, dir: Neg }) + .to_owned_vec() + } } - let mut indices = vec::from_fn(length, |i| i); - loop { - if !fun(permutation) { return true; } - // find largest k such that indices[k] < indices[k+1] - // if no such k exists, all permutations have been generated - let mut k = length - 2; - while k > 0 && indices[k] >= indices[k+1] { - k -= 1; +} + +enum Direction { Pos, Neg } + +/// An Index and Direction together +struct SizeDirection { + size: uint, + dir: Direction, +} + +impl Iterator<(uint, uint)> for ElementSwaps { + #[inline] + fn next(&mut self) -> Option<(uint, uint)> { + fn new_pos(i: uint, s: Direction) -> uint { + i + match s { Pos => 1, Neg => -1 } } - if k == 0 && indices[0] > indices[1] { return true; } - // find largest l such that indices[k] < indices[l] - // k+1 is guaranteed to be such - let mut l = length - 1; - while indices[k] >= indices[l] { - l -= 1; + + // Find the index of the largest mobile element: + // The direction should point into the vector, and the + // swap should be with a smaller `size` element. + let max = self.sdir.iter().map(|&x| x).enumerate() + .filter(|&(i, sd)| + new_pos(i, sd.dir) < self.sdir.len() && + self.sdir[new_pos(i, sd.dir)].size < sd.size) + .max_by(|&(_, sd)| sd.size); + match max { + Some((i, sd)) => { + let j = new_pos(i, sd.dir); + self.sdir.swap(i, j); + + // Swap the direction of each larger SizeDirection + for x in self.sdir.mut_iter() { + if x.size > sd.size { + x.dir = match x.dir { Pos => Neg, Neg => Pos }; + } + } + Some((i, j)) + }, + None => if self.emit_reset && self.sdir.len() > 1 { + self.emit_reset = false; + Some((0, 1)) + } else { + None + } } - // swap indices[k] and indices[l]; sort indices[k+1..] - // (they're just reversed) - indices.swap(k, l); - indices.mut_slice(k+1, length).reverse(); - // fixup permutation based on indices - for i in range(k, length) { - permutation[i] = values[indices[i]].clone(); + } +} + +/// An Iterator that uses `ElementSwaps` to iterate through +/// all possible permutations of a vector. +/// +/// The first iteration yields a clone of the vector as it is, +/// then each successive element is the vector with one +/// swap applied. +/// +/// Generates even and odd permutations alternatingly. +pub struct Permutations { + priv swaps: ElementSwaps, + priv v: ~[T], +} + +impl Iterator<~[T]> for Permutations { + #[inline] + fn next(&mut self) -> Option<~[T]> { + match self.swaps.next() { + None => None, + Some((a, b)) => { + let elt = self.v.clone(); + self.v.swap(a, b); + Some(elt) + } } } } @@ -1141,6 +1191,7 @@ impl<'self, T: TotalOrd> ImmutableTotalOrdVector for &'self [T] { pub trait ImmutableCopyableVector { fn partitioned(&self, f: &fn(&T) -> bool) -> (~[T], ~[T]); unsafe fn unsafe_get(&self, elem: uint) -> T; + fn permutations_iter(self) -> Permutations; } /// Extension methods for vectors @@ -1170,6 +1221,16 @@ impl<'self,T:Clone> ImmutableCopyableVector for &'self [T] { unsafe fn unsafe_get(&self, index: uint) -> T { (*self.unsafe_ref(index)).clone() } + + /// Create an iterator that yields every possible permutation of the + /// vector in succession. + fn permutations_iter(self) -> Permutations { + Permutations{ + swaps: ElementSwaps::new(self.len()), + v: self.to_owned(), + } + } + } #[allow(missing_doc)] @@ -2847,28 +2908,6 @@ mod tests { assert_eq!(v, ~[1, 3, 5]); } - #[test] - fn test_each_permutation() { - let mut results: ~[~[int]]; - - results = ~[]; - do each_permutation([]) |v| { results.push(v.to_owned()); true }; - assert_eq!(results, ~[~[]]); - - results = ~[]; - do each_permutation([7]) |v| { results.push(v.to_owned()); true }; - assert_eq!(results, ~[~[7]]); - - results = ~[]; - do each_permutation([1,1]) |v| { results.push(v.to_owned()); true }; - assert_eq!(results, ~[~[1,1],~[1,1]]); - - results = ~[]; - do each_permutation([5,2,0]) |v| { results.push(v.to_owned()); true }; - assert!(results == - ~[~[5,2,0],~[5,0,2],~[2,5,0],~[2,0,5],~[0,5,2],~[0,2,5]]); - } - #[test] fn test_zip_unzip() { let z1 = ~[(1, 4), (2, 5), (3, 6)]; @@ -2880,6 +2919,58 @@ mod tests { assert_eq!((3, 6), (left[2], right[2])); } + #[test] + fn test_element_swaps() { + let mut v = [1, 2, 3]; + for (i, (a, b)) in ElementSwaps::new(v.len()).enumerate() { + v.swap(a, b); + match i { + 0 => assert_eq!(v, [1, 3, 2]), + 1 => assert_eq!(v, [3, 1, 2]), + 2 => assert_eq!(v, [3, 2, 1]), + 3 => assert_eq!(v, [2, 3, 1]), + 4 => assert_eq!(v, [2, 1, 3]), + 5 => assert_eq!(v, [1, 2, 3]), + _ => fail!(), + } + } + } + + #[test] + fn test_permutations() { + use hashmap; + { + let v: [int, ..0] = []; + let mut it = v.permutations_iter(); + assert_eq!(it.next(), None); + } + { + let v = [~"Hello"]; + let mut it = v.permutations_iter(); + assert_eq!(it.next(), None); + } + { + let v = [1, 2, 3]; + let mut it = v.permutations_iter(); + assert_eq!(it.next(), Some(~[1,2,3])); + assert_eq!(it.next(), Some(~[1,3,2])); + assert_eq!(it.next(), Some(~[3,1,2])); + assert_eq!(it.next(), Some(~[3,2,1])); + assert_eq!(it.next(), Some(~[2,3,1])); + assert_eq!(it.next(), Some(~[2,1,3])); + assert_eq!(it.next(), None); + } + { + // check that we have N! unique permutations + let mut set = hashmap::HashSet::new(); + let v = ['A', 'B', 'C', 'D', 'E', 'F']; + for perm in v.permutations_iter() { + set.insert(perm); + } + assert_eq!(set.len(), 2 * 3 * 4 * 5 * 6); + } + } + #[test] fn test_position_elem() { assert!([].position_elem(&1).is_none()); @@ -3175,13 +3266,12 @@ mod tests { fn test_permute_fail() { let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)]; let mut i = 0; - do each_permutation(v) |_elt| { + for _ in v.permutations_iter() { if i == 2 { fail!() } i += 1; - true - }; + } } #[test] @@ -3493,50 +3583,6 @@ mod tests { assert_eq!(values, [1,4,3,2,5]); } - #[test] - fn test_permutations0() { - let values = []; - let mut v : ~[~[int]] = ~[]; - do each_permutation(values) |p| { - v.push(p.to_owned()); - true - }; - assert_eq!(v, ~[~[]]); - } - - #[test] - fn test_permutations1() { - let values = [1]; - let mut v : ~[~[int]] = ~[]; - do each_permutation(values) |p| { - v.push(p.to_owned()); - true - }; - assert_eq!(v, ~[~[1]]); - } - - #[test] - fn test_permutations2() { - let values = [1,2]; - let mut v : ~[~[int]] = ~[]; - do each_permutation(values) |p| { - v.push(p.to_owned()); - true - }; - assert_eq!(v, ~[~[1,2],~[2,1]]); - } - - #[test] - fn test_permutations3() { - let values = [1,2,3]; - let mut v : ~[~[int]] = ~[]; - do each_permutation(values) |p| { - v.push(p.to_owned()); - true - }; - assert_eq!(v, ~[~[1,2,3],~[1,3,2],~[2,1,3],~[2,3,1],~[3,1,2],~[3,2,1]]); - } - #[test] fn test_vec_zero() { use num::Zero; From 77dff93a4baa4164311e14763cfcbb05e410359b Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Mon, 9 Sep 2013 18:32:35 +0200 Subject: [PATCH 3/5] std::vec: Update module doc text Update for a lot of changes (not many free functions left), add examples of the important methods `slice` and `push`, and write a short bit about iteration. --- src/libstd/vec.rs | 79 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 0a453d13714..b55a236566b 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -10,8 +10,9 @@ /*! -The `vec` module contains useful code to help work with vector values. Vectors are Rust's list -type. Vectors contain zero or more values of homogeneous types: +The `vec` module contains useful code to help work with vector values. +Vectors are Rust's list type. Vectors contain zero or more values of +homogeneous types: ~~~ {.rust} let int_vector = [1,2,3]; @@ -27,32 +28,72 @@ represents iteration over a vector. ## Traits -A number of traits that allow you to accomplish tasks with vectors, like the -`MutableVector` and `ImmutableVector` traits. +A number of traits add methods that allow you to accomplish tasks with vectors. + +Traits defined for the `&[T]` type (a vector slice), have methods that can be +called on either owned vectors, denoted `~[T]`, or on vector slices themselves. +These traits include `ImmutableVector`, and `MutableVector` for the `&mut [T]` +case. + +An example is the method `.slice(a, b)` that returns an immutable "view" into +a vector or a vector slice from the index interval `[a, b)`: + +~~~ {.rust} +let numbers = [0, 1, 2]; +let last_numbers = numbers.slice(1, 3); +// last_numbers is now &[1, 2] +~~~ + +Traits defined for the `~[T]` type, like `OwnedVector`, can only be called +on such vectors. These methods deal with adding elements or otherwise changing +the allocation of the vector. + +An example is the method `.push(element)` that will add an element at the end +of the vector: + +~~~ {.rust} +let mut numbers = ~[0, 1, 2]; +numbers.push(7); +// numbers is now ~[0, 1, 2, 7]; +~~~ ## Implementations of other traits -Vectors are a very useful type, and so there's tons of implementations of -traits found elsewhere. Some notable examples: +Vectors are a very useful type, and so there's several implementations of +traits from other modules. Some notable examples: * `Clone` -* `Iterator` -* `Zero` +* `Eq`, `Ord`, `TotalEq`, `TotalOrd` -- vectors can be compared, + if the element type defines the corresponding trait. + +## Iteration + +The method `iter()` returns an iteration value for a vector or a vector slice. +The iterator yields borrowed pointers to the vector's elements, so if the element +type of the vector is `int`, the element type of the iterator is `&int`. + +~~~ {.rust} +let numbers = [0, 1, 2]; +for &x in numbers.iter() { + println!("{} is a number!", x); +} +~~~ + +* `.rev_iter()` returns an iterator with the same values as `.iter()`, + but going in the reverse order, starting with the back element. +* `.mut_iter()` returns an iterator that allows modifying each value. +* `.move_iter()` converts an owned vector into an iterator that + moves out a value from the vector each iteration. +* Further iterators exist that split, chunk or permute the vector. ## Function definitions -There are a number of different functions that take vectors, here are some -broad categories: +There are a number of free functions that create or take vectors, for example: -* Modifying a vector, like `append` and `grow`. -* Searching in a vector, like `bsearch`. -* Iterating over vectors, like `each_permutation`. -* Functional transformations on vectors, like `map` and `partition`. -* Stack/queue operations, like `push`/`pop` and `shift`/`unshift`. -* Cons-y operations, like `head` and `tail`. -* Zipper operations, like `zip` and `unzip`. - -And much, much more. +* Creating a vector, like `from_elem` and `from_fn` +* Creating a vector with a given size: `with_capacity` +* Modifying a vector and returning it, like `append` +* Operations on paired elements, like `unzip`. */ From 5f69a58e0ccf3d85b5f12f26ecf78ee7e7fec270 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Tue, 10 Sep 2013 03:55:34 +0200 Subject: [PATCH 4/5] std::vec: Remove the function same_length The basic construct x.len() == y.len() is just as simple. This function used to be a precondition (not sure about the terminology), so it had to be a function. This is not relevant any more. --- src/librustc/middle/typeck/infer/combine.rs | 4 ++-- src/libstd/vec.rs | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index b04719ee3ce..693aee83061 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -88,7 +88,7 @@ pub trait Combine { // future we could allow type parameters to declare a // variance. - if vec::same_length(as_, bs) { + if as_.len() == bs.len() { result::fold_(as_.iter().zip(bs.iter()) .map(|(a, b)| eq_tys(self, *a, *b))) .then(|| Ok(as_.to_owned())) @@ -419,7 +419,7 @@ pub fn super_fn_sigs( this: &C, a: &ty::FnSig, b: &ty::FnSig) -> cres { fn argvecs(this: &C, a_args: &[ty::t], b_args: &[ty::t]) -> cres<~[ty::t]> { - if vec::same_length(a_args, b_args) { + if a_args.len() == b_args.len() { result::collect(a_args.iter().zip(b_args.iter()) .map(|(a, b)| this.args(*a, *b))) } else { diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index b55a236566b..27566bf23c8 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -123,11 +123,6 @@ use unstable::raw::{Box, Repr, Slice, Vec}; use vec; use util; -/// Returns true if two vectors have the same length -pub fn same_length(xs: &[T], ys: &[U]) -> bool { - xs.len() == ys.len() -} - /** * Creates and initializes an owned vector. * From c11ee0fb6719e38820762308d67f70cee000bed8 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Tue, 10 Sep 2013 05:50:11 +0200 Subject: [PATCH 5/5] std::at_vec and vec: Unify build_sized, build_sized_opt into build These functions have very few users since they are mostly replaced by iterator-based constructions. Convert a few remaining users in-tree, and reduce the number of functions by basically renaming build_sized_opt to build, and removing the other two. This for both the vec and the at_vec versions. --- src/libextra/base64.rs | 7 +-- src/librustc/middle/typeck/infer/combine.rs | 1 - .../typeck/infer/region_inference/mod.rs | 14 ++--- src/libstd/at_vec.rs | 58 +++++-------------- src/libstd/io.rs | 2 +- src/libstd/vec.rs | 44 ++------------ src/libsyntax/ext/deriving/generic.rs | 2 +- src/test/run-pass/issue-3563-3.rs | 2 +- 8 files changed, 30 insertions(+), 100 deletions(-) diff --git a/src/libextra/base64.rs b/src/libextra/base64.rs index 525ff658dba..f50108d4eae 100644 --- a/src/libextra/base64.rs +++ b/src/libextra/base64.rs @@ -315,11 +315,8 @@ mod test { use std::vec; do 1000.times { - let v: ~[u8] = do vec::build |push| { - do task_rng().gen_uint_range(1, 100).times { - push(random()); - } - }; + let times = task_rng().gen_uint_range(1, 100); + let v = vec::from_fn(times, |_| random::()); assert_eq!(v.to_base64(STANDARD).from_base64().unwrap(), v); } } diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 693aee83061..9fc29250ed0 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -61,7 +61,6 @@ use middle::typeck::infer::{TypeTrace}; use util::common::indent; use std::result; -use std::vec; use syntax::ast::{Onceness, purity}; use syntax::ast; use syntax::opt_vec; diff --git a/src/librustc/middle/typeck/infer/region_inference/mod.rs b/src/librustc/middle/typeck/infer/region_inference/mod.rs index 91b6a4ce3bc..c14e49f37e5 100644 --- a/src/librustc/middle/typeck/infer/region_inference/mod.rs +++ b/src/librustc/middle/typeck/infer/region_inference/mod.rs @@ -373,14 +373,12 @@ impl RegionVarBindings { pub fn vars_created_since_snapshot(&mut self, snapshot: uint) -> ~[RegionVid] { - do vec::build |push| { - for &elt in self.undo_log.slice_from(snapshot).iter() { - match elt { - AddVar(vid) => push(vid), - _ => () - } - } - } + self.undo_log.slice_from(snapshot).iter() + .filter_map(|&elt| match elt { + AddVar(vid) => Some(vid), + _ => None + }) + .collect() } pub fn tainted(&mut self, snapshot: uint, r0: Region) -> ~[Region] { diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs index c192803efff..27bef1214b2 100644 --- a/src/libstd/at_vec.rs +++ b/src/libstd/at_vec.rs @@ -33,42 +33,7 @@ pub fn capacity(v: @[T]) -> uint { /** * Builds a vector by calling a provided function with an argument * function that pushes an element to the back of a vector. - * This version takes an initial size for the vector. - * - * # Arguments - * - * * size - An initial size of the vector to reserve - * * builder - A function that will construct the vector. It receives - * as an argument a function that will push an element - * onto the vector being constructed. - */ -#[inline] -pub fn build_sized(size: uint, builder: &fn(push: &fn(v: A))) -> @[A] { - let mut vec = @[]; - unsafe { raw::reserve(&mut vec, size); } - builder(|x| unsafe { raw::push(&mut vec, x) }); - vec -} - -/** - * Builds a vector by calling a provided function with an argument - * function that pushes an element to the back of a vector. - * - * # Arguments - * - * * builder - A function that will construct the vector. It receives - * as an argument a function that will push an element - * onto the vector being constructed. - */ -#[inline] -pub fn build(builder: &fn(push: &fn(v: A))) -> @[A] { - build_sized(4, builder) -} - -/** - * Builds a vector by calling a provided function with an argument - * function that pushes an element to the back of a vector. - * This version takes an initial size for the vector. + * The initial size for the vector may optionally be specified * * # Arguments * @@ -78,8 +43,11 @@ pub fn build(builder: &fn(push: &fn(v: A))) -> @[A] { * onto the vector being constructed. */ #[inline] -pub fn build_sized_opt(size: Option, builder: &fn(push: &fn(v: A))) -> @[A] { - build_sized(size.unwrap_or_default(4), builder) +pub fn build(size: Option, builder: &fn(push: &fn(v: A))) -> @[A] { + let mut vec = @[]; + unsafe { raw::reserve(&mut vec, size.unwrap_or_default(4)); } + builder(|x| unsafe { raw::push(&mut vec, x) }); + vec } // Appending @@ -88,7 +56,7 @@ pub fn build_sized_opt(size: Option, builder: &fn(push: &fn(v: A))) -> /// `lhs`. Afterwards, the `lhs` is then returned for use again. #[inline] pub fn append(lhs: @[T], rhs: &[T]) -> @[T] { - do build_sized(lhs.len() + rhs.len()) |push| { + do build(Some(lhs.len() + rhs.len())) |push| { for x in lhs.iter() { push((*x).clone()); } @@ -101,7 +69,7 @@ pub fn append(lhs: @[T], rhs: &[T]) -> @[T] { /// Apply a function to each element of a vector and return the results pub fn map(v: &[T], f: &fn(x: &T) -> U) -> @[U] { - do build_sized(v.len()) |push| { + do build(Some(v.len())) |push| { for elem in v.iter() { push(f(elem)); } @@ -115,7 +83,7 @@ pub fn map(v: &[T], f: &fn(x: &T) -> U) -> @[U] { * to the value returned by the function `op`. */ pub fn from_fn(n_elts: uint, op: &fn(uint) -> T) -> @[T] { - do build_sized(n_elts) |push| { + do build(Some(n_elts)) |push| { let mut i: uint = 0u; while i < n_elts { push(op(i)); i += 1u; } } @@ -128,7 +96,7 @@ pub fn from_fn(n_elts: uint, op: &fn(uint) -> T) -> @[T] { * to the value `t`. */ pub fn from_elem(n_elts: uint, t: T) -> @[T] { - do build_sized(n_elts) |push| { + do build(Some(n_elts)) |push| { let mut i: uint = 0u; while i < n_elts { push(t.clone()); @@ -312,7 +280,7 @@ mod test { fn test() { // Some code that could use that, then: fn seq_range(lo: uint, hi: uint) -> @[uint] { - do build |push| { + do build(None) |push| { for i in range(lo, hi) { push(i); } @@ -359,7 +327,7 @@ mod test { fn bench_build_sized(b: &mut bh) { let len = 64; do b.iter { - build_sized(len, |push| for i in range(0, 1024) { push(i) }); + build(Some(len), |push| for i in range(0, 1024) { push(i) }); } } @@ -367,7 +335,7 @@ mod test { fn bench_build(b: &mut bh) { do b.iter { for i in range(0, 95) { - build(|push| push(i)); + build(None, |push| push(i)); } } } diff --git a/src/libstd/io.rs b/src/libstd/io.rs index ee948446614..ee4100f1ec9 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -777,7 +777,7 @@ impl ReaderUtil for T { } fn read_lines(&self) -> ~[~str] { - do vec::build |push| { + do vec::build(None) |push| { do self.each_line |line| { push(line.to_owned()); true diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 27566bf23c8..c45e37477ce 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -194,41 +194,7 @@ pub fn with_capacity(capacity: uint) -> ~[T] { /** * Builds a vector by calling a provided function with an argument * function that pushes an element to the back of a vector. - * This version takes an initial capacity for the vector. - * - * # Arguments - * - * * size - An initial size of the vector to reserve - * * builder - A function that will construct the vector. It receives - * as an argument a function that will push an element - * onto the vector being constructed. - */ -#[inline] -pub fn build_sized(size: uint, builder: &fn(push: &fn(v: A))) -> ~[A] { - let mut vec = with_capacity(size); - builder(|x| vec.push(x)); - vec -} - -/** - * Builds a vector by calling a provided function with an argument - * function that pushes an element to the back of a vector. - * - * # Arguments - * - * * builder - A function that will construct the vector. It receives - * as an argument a function that will push an element - * onto the vector being constructed. - */ -#[inline] -pub fn build(builder: &fn(push: &fn(v: A))) -> ~[A] { - build_sized(4, builder) -} - -/** - * Builds a vector by calling a provided function with an argument - * function that pushes an element to the back of a vector. - * This version takes an initial size for the vector. + * The initial capacity for the vector may optionally be specified. * * # Arguments * @@ -238,8 +204,10 @@ pub fn build(builder: &fn(push: &fn(v: A))) -> ~[A] { * onto the vector being constructed. */ #[inline] -pub fn build_sized_opt(size: Option, builder: &fn(push: &fn(v: A))) -> ~[A] { - build_sized(size.unwrap_or_default(4), builder) +pub fn build(size: Option, builder: &fn(push: &fn(v: A))) -> ~[A] { + let mut vec = with_capacity(size.unwrap_or_default(4)); + builder(|x| vec.push(x)); + vec } /// An iterator over the slices of a vector separated by elements that @@ -3248,7 +3216,7 @@ mod tests { #[test] #[should_fail] fn test_build_fail() { - do build |push| { + do build(None) |push| { push((~0, @0)); push((~0, @0)); push((~0, @0)); diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index 7050cfbedb7..8221be1bbcb 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -958,7 +958,7 @@ fn create_struct_pattern(cx: @ExtCtxt, // struct_type is definitely not Unknown, since struct_def.fields // must be nonempty to reach here let pattern = if struct_type == Record { - let field_pats = do vec::build |push| { + let field_pats = do vec::build(None) |push| { for (&pat, &(id, _)) in subpats.iter().zip(ident_expr.iter()) { // id is guaranteed to be Some push(ast::FieldPat { ident: id.unwrap(), pat: pat }) diff --git a/src/test/run-pass/issue-3563-3.rs b/src/test/run-pass/issue-3563-3.rs index e6429aa5508..3c4c4889ba2 100644 --- a/src/test/run-pass/issue-3563-3.rs +++ b/src/test/run-pass/issue-3563-3.rs @@ -66,7 +66,7 @@ impl Drop for AsciiArt { fn AsciiArt(width: uint, height: uint, fill: char) -> AsciiArt { // Use an anonymous function to build a vector of vectors containing // blank characters for each position in our canvas. - let lines = do vec::build_sized(height) |push| { + let lines = do vec::build(Some(height)) |push| { do height.times { push(vec::from_elem(width, '.')); }