Skip to content

Commit

Permalink
auto merge of #9062 : blake2-ppc/rust/vec-iterator, r=alexcrichton
Browse files Browse the repository at this point in the history
Visit the free functions of std::vec and reimplement or remove some. Most prominently, remove `each_permutation` and replace with two iterators, ElementSwaps and Permutations.

Replace unzip, unzip_slice with an updated `unzip` that works with an iterator argument.

Replace each_permutation with a Permutation iterator. The new permutation iterator is more efficient since it uses an algorithm that produces permutations in an order where each is only one element swap apart, including swapping back to the original state with one swap at the end.

Unify the seldomly used functions `build`, `build_sized`, `build_sized_opt` into just one function `build`.

Remove `equal_sizes`
  • Loading branch information
bors committed Sep 10, 2013
2 parents 8c7c0b4 + c11ee0f commit 7820fb5
Show file tree
Hide file tree
Showing 10 changed files with 268 additions and 274 deletions.
7 changes: 2 additions & 5 deletions src/libextra/base64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<u8>());
assert_eq!(v.to_base64(STANDARD).from_base64().unwrap(), v);
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/librustc/middle/typeck/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -88,7 +87,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()))
Expand Down Expand Up @@ -419,7 +418,7 @@ pub fn super_fn_sigs<C:Combine>(
this: &C, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {

fn argvecs<C:Combine>(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 {
Expand Down
14 changes: 6 additions & 8 deletions src/librustc/middle/typeck/infer/region_inference/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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] {
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ pub fn parse_config_(
process_output: Process
) -> Result<Config, ~str> {
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 {
Expand Down
54 changes: 11 additions & 43 deletions src/libstd/at_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,62 +33,30 @@ pub fn capacity<T>(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.
* The initial size for the vector may optionally be specified
*
* # Arguments
*
* * size - An initial size of the vector to reserve
* * size - An option, maybe containing 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<A>(size: uint, builder: &fn(push: &fn(v: A))) -> @[A] {
pub fn build<A>(size: Option<uint>, builder: &fn(push: &fn(v: A))) -> @[A] {
let mut vec = @[];
unsafe { raw::reserve(&mut vec, size); }
unsafe { raw::reserve(&mut vec, size.unwrap_or_default(4)); }
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<A>(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.
*
* # Arguments
*
* * size - An option, maybe containing 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_opt<A>(size: Option<uint>, builder: &fn(push: &fn(v: A))) -> @[A] {
build_sized(size.unwrap_or_default(4), builder)
}

// Appending

/// Iterates over the `rhs` vector, copying each element and appending it to the
/// `lhs`. Afterwards, the `lhs` is then returned for use again.
#[inline]
pub fn append<T:Clone>(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());
}
Expand All @@ -101,7 +69,7 @@ pub fn append<T:Clone>(lhs: @[T], rhs: &[T]) -> @[T] {

/// Apply a function to each element of a vector and return the results
pub fn map<T, U>(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));
}
Expand All @@ -115,7 +83,7 @@ pub fn map<T, U>(v: &[T], f: &fn(x: &T) -> U) -> @[U] {
* to the value returned by the function `op`.
*/
pub fn from_fn<T>(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; }
}
Expand All @@ -128,7 +96,7 @@ pub fn from_fn<T>(n_elts: uint, op: &fn(uint) -> T) -> @[T] {
* to the value `t`.
*/
pub fn from_elem<T:Clone>(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());
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -359,15 +327,15 @@ 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) });
}
}

#[bench]
fn bench_build(b: &mut bh) {
do b.iter {
for i in range(0, 95) {
build(|push| push(i));
build(None, |push| push(i));
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ impl<T:Reader> 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
Expand Down
8 changes: 4 additions & 4 deletions src/libstd/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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() {
Expand Down Expand Up @@ -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::<int>()));
let (port, chan) = stream();
do 10.times { chan.send(31337); }
let mut ports = ports;
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 7820fb5

Please sign in to comment.