Skip to content

Commit

Permalink
Make a bunch more of the iteration functions/methods marked pure. Closes
Browse files Browse the repository at this point in the history
  • Loading branch information
msullivan committed Aug 23, 2012
1 parent 0f0a977 commit 226fd87
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 112 deletions.
20 changes: 19 additions & 1 deletion src/libcore/at_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import ptr::addr_of;

export init_op;
export capacity;
export build_sized, build;
export build_sized, build, build_sized_opt;
export map;
export from_fn, from_elem;
export unsafe;
Expand Down Expand Up @@ -78,6 +78,24 @@ pure fn build<A>(builder: fn(push: pure fn(+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 recieves
* as an argument a function that will push an element
* onto the vector being constructed.
*/
#[inline(always)]
pure fn build_sized_opt<A>(size: option<uint>,
builder: fn(push: pure fn(+A))) -> @[A] {
build_sized(size.get_default(4), builder)
}

// Appending
#[inline(always)]
pure fn append<T: copy>(lhs: @[T], rhs: &[const T]) -> @[T] {
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Path = path::Path;
import tuple::{TupleOps, ExtendedTupleOps};
import str::{StrSlice, UniqueStr};
import vec::{ConstVector, CopyableVector, ImmutableVector};
import vec::{ImmutableCopyableVector, IterTraitExtensions};
import vec::{ImmutableCopyableVector};
import iter::{BaseIter, ExtendedIter, CopyableIter, Times, TimesIx};
import num::Num;
import ptr::Ptr;
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/int-template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ impl T: iter::Times {
will execute the given function exactly x times. If we assume that \
`x` is an int, this is functionally equivalent to \
`for int::range(0, x) |_i| { /* anything */ }`."]
fn times(it: fn() -> bool) {
pure fn times(it: fn() -> bool) {
if self < 0 {
fail fmt!{"The .times method expects a nonnegative number, \
but found %?", self};
Expand All @@ -111,7 +111,7 @@ impl T: iter::Times {
impl T: iter::TimesIx {
#[inline(always)]
/// Like `times`, but provides an index
fn timesi(it: fn(uint) -> bool) {
pure fn timesi(it: fn(uint) -> bool) {
let slf = self as uint;
if slf < 0u {
fail fmt!{"The .timesi method expects a nonnegative number, \
Expand Down
38 changes: 17 additions & 21 deletions src/libcore/iter-trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,39 @@ import inst::{IMPL_T, EACH, SIZE_HINT};
export extensions;

impl<A> IMPL_T<A>: iter::BaseIter<A> {
fn each(blk: fn(A) -> bool) { EACH(self, blk) }
fn size_hint() -> option<uint> { SIZE_HINT(self) }
pure fn each(blk: fn(A) -> bool) { EACH(self, blk) }
pure fn size_hint() -> option<uint> { SIZE_HINT(self) }
}

impl<A> IMPL_T<A>: iter::ExtendedIter<A> {
fn eachi(blk: fn(uint, A) -> bool) { iter::eachi(self, blk) }
fn all(blk: fn(A) -> bool) -> bool { iter::all(self, blk) }
fn any(blk: fn(A) -> bool) -> bool { iter::any(self, blk) }
fn foldl<B>(+b0: B, blk: fn(B, A) -> B) -> B {
pure fn eachi(blk: fn(uint, A) -> bool) { iter::eachi(self, blk) }
pure fn all(blk: fn(A) -> bool) -> bool { iter::all(self, blk) }
pure fn any(blk: fn(A) -> bool) -> bool { iter::any(self, blk) }
pure fn foldl<B>(+b0: B, blk: fn(B, A) -> B) -> B {
iter::foldl(self, b0, blk)
}
fn contains(x: A) -> bool { iter::contains(self, x) }
fn count(x: A) -> uint { iter::count(self, x) }
fn position(f: fn(A) -> bool) -> option<uint> {
pure fn contains(x: A) -> bool { iter::contains(self, x) }
pure fn count(x: A) -> uint { iter::count(self, x) }
pure fn position(f: fn(A) -> bool) -> option<uint> {
iter::position(self, f)
}
}

impl<A: copy> IMPL_T<A>: iter::CopyableIter<A> {
fn filter_to_vec(pred: fn(A) -> bool) -> ~[A] {
pure fn filter_to_vec(pred: fn(A) -> bool) -> ~[A] {
iter::filter_to_vec(self, pred)
}
fn map_to_vec<B>(op: fn(A) -> B) -> ~[B] { iter::map_to_vec(self, op) }
fn to_vec() -> ~[A] { iter::to_vec(self) }
pure fn map_to_vec<B>(op: fn(A) -> B) -> ~[B] {
iter::map_to_vec(self, op)
}
pure fn to_vec() -> ~[A] { iter::to_vec(self) }

// FIXME--bug in resolve prevents this from working (#2611)
// fn flat_map_to_vec<B:copy,IB:base_iter<B>>(op: fn(A) -> IB) -> ~[B] {
// iter::flat_map_to_vec(self, op)
// }

fn min() -> A { iter::min(self) }
fn max() -> A { iter::max(self) }

fn find(p: fn(A) -> bool) -> option<A> {
for self.each |i| {
if p(i) { return some(i) }
}
return none;
}
pure fn min() -> A { iter::min(self) }
pure fn max() -> A { iter::max(self) }
pure fn find(p: fn(A) -> bool) -> option<A> { iter::find(self, p) }
}
2 changes: 1 addition & 1 deletion src/libcore/iter-trait/dlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ pure fn EACH<A>(self: IMPL_T<A>, f: fn(A) -> bool) {
}
}

fn SIZE_HINT<A>(self: IMPL_T<A>) -> option<uint> {
pure fn SIZE_HINT<A>(self: IMPL_T<A>) -> option<uint> {
some(self.len())
}
6 changes: 3 additions & 3 deletions src/libcore/iter-trait/dvec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ type IMPL_T<A> = dvec::DVec<A>;
*
* Attempts to access this dvec during iteration will fail.
*/
fn EACH<A>(self: IMPL_T<A>, f: fn(A) -> bool) {
self.swap(|v| { vec::each(v, f); v })
pure fn EACH<A>(self: IMPL_T<A>, f: fn(A) -> bool) {
unsafe { self.swap(|v| { vec::each(v, f); v }) }
}

fn SIZE_HINT<A>(self: IMPL_T<A>) -> option<uint> {
pure fn SIZE_HINT<A>(self: IMPL_T<A>) -> option<uint> {
some(self.len())
}
2 changes: 1 addition & 1 deletion src/libcore/iter-trait/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pure fn EACH<A>(self: IMPL_T<A>, f: fn(A) -> bool) {
}
}

fn SIZE_HINT<A>(self: IMPL_T<A>) -> option<uint> {
pure fn SIZE_HINT<A>(self: IMPL_T<A>) -> option<uint> {
match self {
none => some(0u),
some(_) => some(1u)
Expand Down
99 changes: 53 additions & 46 deletions src/libcore/iter.rs
Original file line number Diff line number Diff line change
@@ -1,107 +1,106 @@
trait BaseIter<A> {
fn each(blk: fn(A) -> bool);
fn size_hint() -> option<uint>;
pure fn each(blk: fn(A) -> bool);
pure fn size_hint() -> option<uint>;
}

trait ExtendedIter<A> {
fn eachi(blk: fn(uint, A) -> bool);
fn all(blk: fn(A) -> bool) -> bool;
fn any(blk: fn(A) -> bool) -> bool;
fn foldl<B>(+b0: B, blk: fn(B, A) -> B) -> B;
fn contains(x: A) -> bool;
fn count(x: A) -> uint;
fn position(f: fn(A) -> bool) -> option<uint>;
pure fn eachi(blk: fn(uint, A) -> bool);
pure fn all(blk: fn(A) -> bool) -> bool;
pure fn any(blk: fn(A) -> bool) -> bool;
pure fn foldl<B>(+b0: B, blk: fn(B, A) -> B) -> B;
pure fn contains(x: A) -> bool;
pure fn count(x: A) -> uint;
pure fn position(f: fn(A) -> bool) -> option<uint>;
}

trait Times {
fn times(it: fn() -> bool);
pure fn times(it: fn() -> bool);
}
trait TimesIx{
fn timesi(it: fn(uint) -> bool);
pure fn timesi(it: fn(uint) -> bool);
}

trait CopyableIter<A:copy> {
fn filter_to_vec(pred: fn(A) -> bool) -> ~[A];
fn map_to_vec<B>(op: fn(A) -> B) -> ~[B];
fn to_vec() -> ~[A];
fn min() -> A;
fn max() -> A;
fn find(p: fn(A) -> bool) -> option<A>;
pure fn filter_to_vec(pred: fn(A) -> bool) -> ~[A];
pure fn map_to_vec<B>(op: fn(A) -> B) -> ~[B];
pure fn to_vec() -> ~[A];
pure fn min() -> A;
pure fn max() -> A;
pure fn find(p: fn(A) -> bool) -> option<A>;
}

fn eachi<A,IA:BaseIter<A>>(self: IA, blk: fn(uint, A) -> bool) {
pure fn eachi<A,IA:BaseIter<A>>(self: IA, blk: fn(uint, A) -> bool) {
let mut i = 0u;
for self.each |a| {
if !blk(i, a) { break; }
i += 1u;
}
}

fn all<A,IA:BaseIter<A>>(self: IA, blk: fn(A) -> bool) -> bool {
pure fn all<A,IA:BaseIter<A>>(self: IA, blk: fn(A) -> bool) -> bool {
for self.each |a| {
if !blk(a) { return false; }
}
return true;
}

fn any<A,IA:BaseIter<A>>(self: IA, blk: fn(A) -> bool) -> bool {
pure fn any<A,IA:BaseIter<A>>(self: IA, blk: fn(A) -> bool) -> bool {
for self.each |a| {
if blk(a) { return true; }
}
return false;
}

fn filter_to_vec<A:copy,IA:BaseIter<A>>(self: IA,
pure fn filter_to_vec<A:copy,IA:BaseIter<A>>(self: IA,
prd: fn(A) -> bool) -> ~[A] {
let mut result = ~[];
self.size_hint().iter(|hint| vec::reserve(result, hint));
for self.each |a| {
if prd(a) { vec::push(result, a); }
do vec::build_sized_opt(self.size_hint()) |push| {
for self.each |a| {
if prd(a) { push(a); }
}
}
return result;
}

fn map_to_vec<A:copy,B,IA:BaseIter<A>>(self: IA, op: fn(A) -> B) -> ~[B] {
let mut result = ~[];
self.size_hint().iter(|hint| vec::reserve(result, hint));
for self.each |a| {
vec::push(result, op(a));
pure fn map_to_vec<A:copy,B,IA:BaseIter<A>>(self: IA, op: fn(A) -> B)
-> ~[B] {
do vec::build_sized_opt(self.size_hint()) |push| {
for self.each |a| {
push(op(a));
}
}
return result;
}

fn flat_map_to_vec<A:copy,B:copy,IA:BaseIter<A>,IB:BaseIter<B>>(
pure fn flat_map_to_vec<A:copy,B:copy,IA:BaseIter<A>,IB:BaseIter<B>>(
self: IA, op: fn(A) -> IB) -> ~[B] {

let mut result = ~[];
for self.each |a| {
for op(a).each |b| {
vec::push(result, b);
do vec::build |push| {
for self.each |a| {
for op(a).each |b| {
push(b);
}
}
}
return result;
}

fn foldl<A,B,IA:BaseIter<A>>(self: IA, +b0: B, blk: fn(B, A) -> B) -> B {
pure fn foldl<A,B,IA:BaseIter<A>>(self: IA, +b0: B, blk: fn(B, A) -> B) -> B {
let mut b <- b0;
for self.each |a| {
b = blk(b, a);
}
return b;
}

fn to_vec<A:copy,IA:BaseIter<A>>(self: IA) -> ~[A] {
pure fn to_vec<A:copy,IA:BaseIter<A>>(self: IA) -> ~[A] {
foldl::<A,~[A],IA>(self, ~[], |r, a| vec::append(r, ~[a]))
}

fn contains<A,IA:BaseIter<A>>(self: IA, x: A) -> bool {
pure fn contains<A,IA:BaseIter<A>>(self: IA, x: A) -> bool {
for self.each |a| {
if a == x { return true; }
}
return false;
}

fn count<A,IA:BaseIter<A>>(self: IA, x: A) -> uint {
pure fn count<A,IA:BaseIter<A>>(self: IA, x: A) -> uint {
do foldl(self, 0u) |count, value| {
if value == x {
count + 1u
Expand All @@ -111,7 +110,7 @@ fn count<A,IA:BaseIter<A>>(self: IA, x: A) -> uint {
}
}

fn position<A,IA:BaseIter<A>>(self: IA, f: fn(A) -> bool)
pure fn position<A,IA:BaseIter<A>>(self: IA, f: fn(A) -> bool)
-> option<uint> {
let mut i = 0;
for self.each |a| {
Expand All @@ -125,15 +124,15 @@ fn position<A,IA:BaseIter<A>>(self: IA, f: fn(A) -> bool)
// iter interface, such as would provide "reach" in addition to "each". as is,
// it would have to be implemented with foldr, which is too inefficient.

fn repeat(times: uint, blk: fn() -> bool) {
pure fn repeat(times: uint, blk: fn() -> bool) {
let mut i = 0u;
while i < times {
if !blk() { break }
i += 1u;
}
}

fn min<A:copy,IA:BaseIter<A>>(self: IA) -> A {
pure fn min<A:copy,IA:BaseIter<A>>(self: IA) -> A {
match do foldl::<A,option<A>,IA>(self, none) |a, b| {
match a {
some(a_) if a_ < b => {
Expand All @@ -149,7 +148,7 @@ fn min<A:copy,IA:BaseIter<A>>(self: IA) -> A {
}
}

fn max<A:copy,IA:BaseIter<A>>(self: IA) -> A {
pure fn max<A:copy,IA:BaseIter<A>>(self: IA) -> A {
match do foldl::<A,option<A>,IA>(self, none) |a, b| {
match a {
some(a_) if a_ > b => {
Expand All @@ -165,6 +164,14 @@ fn max<A:copy,IA:BaseIter<A>>(self: IA) -> A {
}
}

pure fn find<A: copy,IA:BaseIter<A>>(self: IA,
p: fn(A) -> bool) -> option<A> {
for self.each |i| {
if p(i) { return some(i) }
}
return none;
}

/*
#[test]
fn test_enumerate() {
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/uint-template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl T: iter::Times {
will execute the given function exactly x times. If we assume that \
`x` is an int, this is functionally equivalent to \
`for int::range(0, x) |_i| { /* anything */ }`."]
fn times(it: fn() -> bool) {
pure fn times(it: fn() -> bool) {
let mut i = self;
while i > 0 {
if !it() { break }
Expand All @@ -99,7 +99,7 @@ impl T: iter::Times {
impl T: iter::TimesIx {
#[inline(always)]
/// Like `times`, but with an index, `eachi`-style.
fn timesi(it: fn(uint) -> bool) {
pure fn timesi(it: fn(uint) -> bool) {
let slf = self as uint;
let mut i = 0u;
while i < slf {
Expand Down
Loading

0 comments on commit 226fd87

Please sign in to comment.