Skip to content

Commit 1ce7902

Browse files
committed
Add a Buildable interface for constructing general sequences. Work on #2921.
1 parent c87e9a5 commit 1ce7902

File tree

3 files changed

+125
-9
lines changed

3 files changed

+125
-9
lines changed

src/libcore/at_vec.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ extern mod rusti {
2424
fn move_val_init<T>(&dst: T, -src: T);
2525
}
2626

27-
/// A function used to initialize the elements of a vector
28-
type InitOp<T> = fn(uint) -> T;
29-
3027
/// Returns the number of elements the vector can hold without reallocating
3128
#[inline(always)]
3229
pure fn capacity<T>(&&v: @[const T]) -> uint {
@@ -115,7 +112,7 @@ pure fn map<T, U>(v: &[T], f: fn(T) -> U) -> @[U] {
115112
* Creates an immutable vector of size `n_elts` and initializes the elements
116113
* to the value returned by the function `op`.
117114
*/
118-
pure fn from_fn<T>(n_elts: uint, op: InitOp<T>) -> @[T] {
115+
pure fn from_fn<T>(n_elts: uint, op: iter::InitOp<T>) -> @[T] {
119116
do build_sized(n_elts) |push| {
120117
let mut i: uint = 0u;
121118
while i < n_elts { push(op(i)); i += 1u; }

src/libcore/iter.rs

+122
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
/// A function used to initialize the elements of a sequence
2+
type InitOp<T> = fn(uint) -> T;
3+
14
trait BaseIter<A> {
25
pure fn each(blk: fn(A) -> bool);
36
pure fn size_hint() -> option<uint>;
@@ -29,6 +32,26 @@ trait CopyableIter<A:copy> {
2932
pure fn find(p: fn(A) -> bool) -> option<A>;
3033
}
3134

35+
// A trait for sequences that can be by imperatively pushing elements
36+
// onto them.
37+
trait Buildable<A> {
38+
/**
39+
* Builds a buildable sequence by calling a provided function with
40+
* an argument function that pushes an element onto the back of
41+
* the sequence.
42+
* This version takes an initial size for the sequence.
43+
*
44+
* # Arguments
45+
*
46+
* * size - A hint for an initial size of the sequence
47+
* * builder - A function that will construct the sequence. It recieves
48+
* as an argument a function that will push an element
49+
* onto the sequence being constructed.
50+
*/
51+
static pure fn build_sized(size: uint,
52+
builder: fn(push: pure fn(+A))) -> self;
53+
}
54+
3255
pure fn eachi<A,IA:BaseIter<A>>(self: IA, blk: fn(uint, A) -> bool) {
3356
let mut i = 0u;
3457
for self.each |a| {
@@ -172,6 +195,105 @@ pure fn find<A: copy,IA:BaseIter<A>>(self: IA,
172195
return none;
173196
}
174197

198+
// Some functions for just building
199+
200+
/**
201+
* Builds a sequence by calling a provided function with an argument
202+
* function that pushes an element to the back of a sequence.
203+
*
204+
* # Arguments
205+
*
206+
* * builder - A function that will construct the sequence. It recieves
207+
* as an argument a function that will push an element
208+
* onto the sequence being constructed.
209+
*/
210+
#[inline(always)]
211+
pure fn build<A,B: Buildable<A>>(builder: fn(push: pure fn(+A))) -> B {
212+
build_sized(4, builder)
213+
}
214+
215+
/**
216+
* Builds a sequence by calling a provided function with an argument
217+
* function that pushes an element to the back of a sequence.
218+
* This version takes an initial size for the sequence.
219+
*
220+
* # Arguments
221+
*
222+
* * size - An option, maybe containing initial size of the sequence
223+
* to reserve
224+
* * builder - A function that will construct the sequence. It recieves
225+
* as an argument a function that will push an element
226+
* onto the sequence being constructed.
227+
*/
228+
#[inline(always)]
229+
pure fn build_sized_opt<A,B: Buildable<A>>(
230+
size: option<uint>,
231+
builder: fn(push: pure fn(+A))) -> B {
232+
233+
build_sized(size.get_default(4), builder)
234+
}
235+
236+
// Functions that combine iteration and building
237+
238+
/// Apply a function to each element of an iterable and return the results
239+
fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: IT, f: fn(T) -> U) -> BU {
240+
do build_sized_opt(v.size_hint()) |push| {
241+
for v.each() |elem| {
242+
push(f(elem));
243+
}
244+
}
245+
}
246+
247+
/**
248+
* Creates and initializes a generic sequence from a function
249+
*
250+
* Creates a generic sequence of size `n_elts` and initializes the elements
251+
* to the value returned by the function `op`.
252+
*/
253+
pure fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT {
254+
do build_sized(n_elts) |push| {
255+
let mut i: uint = 0u;
256+
while i < n_elts { push(op(i)); i += 1u; }
257+
}
258+
}
259+
260+
/**
261+
* Creates and initializes a generic sequence with some element
262+
*
263+
* Creates an immutable vector of size `n_elts` and initializes the elements
264+
* to the value `t`.
265+
*/
266+
pure fn from_elem<T: copy,BT: Buildable<T>>(n_elts: uint, t: T) -> BT {
267+
do build_sized(n_elts) |push| {
268+
let mut i: uint = 0u;
269+
while i < n_elts { push(t); i += 1u; }
270+
}
271+
}
272+
273+
/// Appending two generic sequences
274+
#[inline(always)]
275+
pure fn append<T: copy,IT: BaseIter<T>,BT: Buildable<T>>(
276+
lhs: IT, rhs: IT) -> BT {
277+
let size_opt = lhs.size_hint().chain(
278+
|sz1| rhs.size_hint().map(|sz2| sz1+sz2));
279+
do build_sized_opt(size_opt) |push| {
280+
for lhs.each |x| { push(x); }
281+
for rhs.each |x| { push(x); }
282+
}
283+
}
284+
285+
/// Copies a generic sequence, possibly converting it to a different
286+
/// type of sequence.
287+
#[inline(always)]
288+
pure fn copy_seq<T: copy,IT: BaseIter<T>,BT: Buildable<T>>(
289+
v: IT) -> BT {
290+
do build_sized_opt(v.size_hint()) |push| {
291+
for v.each |x| { push(x); }
292+
}
293+
}
294+
295+
296+
175297
/*
176298
#[test]
177299
fn test_enumerate() {

src/libcore/vec.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,6 @@ extern mod rusti {
110110
fn move_val_init<T>(&dst: T, -src: T);
111111
}
112112

113-
/// A function used to initialize the elements of a vector
114-
type InitOp/&<T> = fn(uint) -> T;
115-
116113
/// Returns true if a vector contains no elements
117114
pure fn is_empty<T>(v: &[const T]) -> bool {
118115
as_const_buf(v, |_p, len| len == 0u)
@@ -188,7 +185,7 @@ pure fn len<T>(&&v: &[const T]) -> uint {
188185
* Creates an immutable vector of size `n_elts` and initializes the elements
189186
* to the value returned by the function `op`.
190187
*/
191-
pure fn from_fn<T>(n_elts: uint, op: InitOp<T>) -> ~[T] {
188+
pure fn from_fn<T>(n_elts: uint, op: iter::InitOp<T>) -> ~[T] {
192189
let mut v = ~[];
193190
unchecked{reserve(v, n_elts);}
194191
let mut i: uint = 0u;
@@ -679,7 +676,7 @@ fn grow<T: copy>(&v: ~[const T], n: uint, initval: T) {
679676
* * init_op - A function to call to retreive each appended element's
680677
* value
681678
*/
682-
fn grow_fn<T>(&v: ~[const T], n: uint, op: InitOp<T>) {
679+
fn grow_fn<T>(&v: ~[const T], n: uint, op: iter::InitOp<T>) {
683680
reserve_at_least(v, len(v) + n);
684681
let mut i: uint = 0u;
685682
while i < n { push(v, op(i)); i += 1u; }

0 commit comments

Comments
 (0)