diff --git a/src/libcore/at_vec.rs b/src/libcore/at_vec.rs index 59ed352e1ee..7ae91aebed5 100644 --- a/src/libcore/at_vec.rs +++ b/src/libcore/at_vec.rs @@ -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; @@ -78,6 +78,24 @@ pure fn build(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(size: option, + builder: fn(push: pure fn(+A))) -> @[A] { + build_sized(size.get_default(4), builder) +} + // Appending #[inline(always)] pure fn append(lhs: @[T], rhs: &[const T]) -> @[T] { diff --git a/src/libcore/core.rs b/src/libcore/core.rs index 1fb831b46fa..2f7ae426517 100644 --- a/src/libcore/core.rs +++ b/src/libcore/core.rs @@ -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; diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs index 9ebfec47c7c..cce13589bd5 100644 --- a/src/libcore/int-template.rs +++ b/src/libcore/int-template.rs @@ -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}; @@ -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, \ diff --git a/src/libcore/iter-trait.rs b/src/libcore/iter-trait.rs index 5aeb958f5b2..80ec6ce6fee 100644 --- a/src/libcore/iter-trait.rs +++ b/src/libcore/iter-trait.rs @@ -6,43 +6,39 @@ import inst::{IMPL_T, EACH, SIZE_HINT}; export extensions; impl IMPL_T: iter::BaseIter { - fn each(blk: fn(A) -> bool) { EACH(self, blk) } - fn size_hint() -> option { SIZE_HINT(self) } + pure fn each(blk: fn(A) -> bool) { EACH(self, blk) } + pure fn size_hint() -> option { SIZE_HINT(self) } } impl IMPL_T: iter::ExtendedIter { - 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(+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(+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 { + 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 { iter::position(self, f) } } impl IMPL_T: iter::CopyableIter { - 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(op: fn(A) -> B) -> ~[B] { iter::map_to_vec(self, op) } - fn to_vec() -> ~[A] { iter::to_vec(self) } + pure fn map_to_vec(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>(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 { - 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 { iter::find(self, p) } } diff --git a/src/libcore/iter-trait/dlist.rs b/src/libcore/iter-trait/dlist.rs index 91d6ffa765a..47ac9e7aa37 100644 --- a/src/libcore/iter-trait/dlist.rs +++ b/src/libcore/iter-trait/dlist.rs @@ -29,6 +29,6 @@ pure fn EACH(self: IMPL_T, f: fn(A) -> bool) { } } -fn SIZE_HINT(self: IMPL_T) -> option { +pure fn SIZE_HINT(self: IMPL_T) -> option { some(self.len()) } diff --git a/src/libcore/iter-trait/dvec.rs b/src/libcore/iter-trait/dvec.rs index 5c02f8b5dea..045c52aa4fd 100644 --- a/src/libcore/iter-trait/dvec.rs +++ b/src/libcore/iter-trait/dvec.rs @@ -6,10 +6,10 @@ type IMPL_T = dvec::DVec; * * Attempts to access this dvec during iteration will fail. */ -fn EACH(self: IMPL_T, f: fn(A) -> bool) { - self.swap(|v| { vec::each(v, f); v }) +pure fn EACH(self: IMPL_T, f: fn(A) -> bool) { + unsafe { self.swap(|v| { vec::each(v, f); v }) } } -fn SIZE_HINT(self: IMPL_T) -> option { +pure fn SIZE_HINT(self: IMPL_T) -> option { some(self.len()) } diff --git a/src/libcore/iter-trait/option.rs b/src/libcore/iter-trait/option.rs index 2bcb7bba56e..d0a502813db 100644 --- a/src/libcore/iter-trait/option.rs +++ b/src/libcore/iter-trait/option.rs @@ -7,7 +7,7 @@ pure fn EACH(self: IMPL_T, f: fn(A) -> bool) { } } -fn SIZE_HINT(self: IMPL_T) -> option { +pure fn SIZE_HINT(self: IMPL_T) -> option { match self { none => some(0u), some(_) => some(1u) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 06a1c6c9fba..b5b56756e11 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -1,35 +1,35 @@ trait BaseIter { - fn each(blk: fn(A) -> bool); - fn size_hint() -> option; + pure fn each(blk: fn(A) -> bool); + pure fn size_hint() -> option; } trait ExtendedIter { - fn eachi(blk: fn(uint, A) -> bool); - fn all(blk: fn(A) -> bool) -> bool; - fn any(blk: fn(A) -> bool) -> bool; - fn foldl(+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; + 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(+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; } 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 { - fn filter_to_vec(pred: fn(A) -> bool) -> ~[A]; - fn map_to_vec(op: fn(A) -> B) -> ~[B]; - fn to_vec() -> ~[A]; - fn min() -> A; - fn max() -> A; - fn find(p: fn(A) -> bool) -> option; + pure fn filter_to_vec(pred: fn(A) -> bool) -> ~[A]; + pure fn map_to_vec(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; } -fn eachi>(self: IA, blk: fn(uint, A) -> bool) { +pure fn eachi>(self: IA, blk: fn(uint, A) -> bool) { let mut i = 0u; for self.each |a| { if !blk(i, a) { break; } @@ -37,52 +37,51 @@ fn eachi>(self: IA, blk: fn(uint, A) -> bool) { } } -fn all>(self: IA, blk: fn(A) -> bool) -> bool { +pure fn all>(self: IA, blk: fn(A) -> bool) -> bool { for self.each |a| { if !blk(a) { return false; } } return true; } -fn any>(self: IA, blk: fn(A) -> bool) -> bool { +pure fn any>(self: IA, blk: fn(A) -> bool) -> bool { for self.each |a| { if blk(a) { return true; } } return false; } -fn filter_to_vec>(self: IA, +pure fn filter_to_vec>(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); } - } - return result; -} - -fn map_to_vec>(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)); - } - return result; -} - -fn flat_map_to_vec,IB:BaseIter>( - 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_sized_opt(self.size_hint()) |push| { + for self.each |a| { + if prd(a) { push(a); } } } - return result; } -fn foldl>(self: IA, +b0: B, blk: fn(B, A) -> B) -> B { +pure fn map_to_vec>(self: IA, op: fn(A) -> B) + -> ~[B] { + do vec::build_sized_opt(self.size_hint()) |push| { + for self.each |a| { + push(op(a)); + } + } +} + +pure fn flat_map_to_vec,IB:BaseIter>( + self: IA, op: fn(A) -> IB) -> ~[B] { + + do vec::build |push| { + for self.each |a| { + for op(a).each |b| { + push(b); + } + } + } +} + +pure fn foldl>(self: IA, +b0: B, blk: fn(B, A) -> B) -> B { let mut b <- b0; for self.each |a| { b = blk(b, a); @@ -90,18 +89,18 @@ fn foldl>(self: IA, +b0: B, blk: fn(B, A) -> B) -> B { return b; } -fn to_vec>(self: IA) -> ~[A] { +pure fn to_vec>(self: IA) -> ~[A] { foldl::(self, ~[], |r, a| vec::append(r, ~[a])) } -fn contains>(self: IA, x: A) -> bool { +pure fn contains>(self: IA, x: A) -> bool { for self.each |a| { if a == x { return true; } } return false; } -fn count>(self: IA, x: A) -> uint { +pure fn count>(self: IA, x: A) -> uint { do foldl(self, 0u) |count, value| { if value == x { count + 1u @@ -111,7 +110,7 @@ fn count>(self: IA, x: A) -> uint { } } -fn position>(self: IA, f: fn(A) -> bool) +pure fn position>(self: IA, f: fn(A) -> bool) -> option { let mut i = 0; for self.each |a| { @@ -125,7 +124,7 @@ fn position>(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 } @@ -133,7 +132,7 @@ fn repeat(times: uint, blk: fn() -> bool) { } } -fn min>(self: IA) -> A { +pure fn min>(self: IA) -> A { match do foldl::,IA>(self, none) |a, b| { match a { some(a_) if a_ < b => { @@ -149,7 +148,7 @@ fn min>(self: IA) -> A { } } -fn max>(self: IA) -> A { +pure fn max>(self: IA) -> A { match do foldl::,IA>(self, none) |a, b| { match a { some(a_) if a_ > b => { @@ -165,6 +164,14 @@ fn max>(self: IA) -> A { } } +pure fn find>(self: IA, + p: fn(A) -> bool) -> option { + for self.each |i| { + if p(i) { return some(i) } + } + return none; +} + /* #[test] fn test_enumerate() { diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs index 8e2cdf65c4a..95e4edbba5c 100644 --- a/src/libcore/uint-template.rs +++ b/src/libcore/uint-template.rs @@ -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 } @@ -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 { diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index daf36b21e6f..2c36e6bb5a0 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -18,7 +18,7 @@ export len; export from_fn; export from_elem; export from_slice; -export build, build_sized; +export build, build_sized, build_sized_opt; export to_mut; export from_mut; export head; @@ -259,6 +259,24 @@ pure fn build(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(size: option, + builder: fn(push: pure fn(+A))) -> ~[A] { + build_sized(size.get_default(4), builder) +} + /// Produces a mut vector from an immutable vector. pure fn to_mut(+v: ~[T]) -> ~[mut T] { unsafe { ::unsafe::transmute(v) } @@ -1505,7 +1523,6 @@ impl &[T]: ImmutableVector { trait ImmutableCopyableVector { pure fn filter(f: fn(T) -> bool) -> ~[T]; - pure fn find(f: fn(T) -> bool) -> option; pure fn rfind(f: fn(T) -> bool) -> option; } @@ -1520,15 +1537,6 @@ impl &[T]: ImmutableCopyableVector { */ #[inline] pure fn filter(f: fn(T) -> bool) -> ~[T] { filter(self, f) } - /** - * Search for the first element that matches a given predicate - * - * Apply function `f` to each element of `v`, starting from the first. - * When function `f` returns true then an option containing the element - * is returned. If `f` matches no elements then none is returned. - */ - #[inline] - pure fn find(f: fn(T) -> bool) -> option { find(self, f) } /** * Search for the last element that matches a given predicate * @@ -1756,44 +1764,41 @@ mod u8 { // required in the slice. impl &[A]: iter::BaseIter { - fn each(blk: fn(A) -> bool) { each(self, blk) } - fn size_hint() -> option { some(len(self)) } + pure fn each(blk: fn(A) -> bool) { each(self, blk) } + pure fn size_hint() -> option { some(len(self)) } } impl &[A]: iter::ExtendedIter { - 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(+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(+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 { iter::position(self, f) } + 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 { + iter::position(self, f) + } } -trait IterTraitExtensions { - fn filter_to_vec(pred: fn(A) -> bool) -> ~[A]; - fn map_to_vec(op: fn(A) -> B) -> ~[B]; - fn to_vec() -> ~[A]; - fn min() -> A; - fn max() -> A; -} - -impl &[A]: IterTraitExtensions { - fn filter_to_vec(pred: fn(A) -> bool) -> ~[A] { +impl &[A]: iter::CopyableIter { + pure fn filter_to_vec(pred: fn(A) -> bool) -> ~[A] { iter::filter_to_vec(self, pred) } - fn map_to_vec(op: fn(A) -> B) -> ~[B] { iter::map_to_vec(self, op) } - fn to_vec() -> ~[A] { iter::to_vec(self) } + pure fn map_to_vec(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>(op: fn(A) -> IB) -> ~[B] { // iter::flat_map_to_vec(self, op) // } - fn min() -> A { iter::min(self) } - fn max() -> A { iter::max(self) } + pure fn min() -> A { iter::min(self) } + pure fn max() -> A { iter::max(self) } + pure fn find(p: fn(A) -> bool) -> option { iter::find(self, p) } } // ___________________________________________________________________________