|
| 1 | +/// A function used to initialize the elements of a sequence |
| 2 | +type InitOp<T> = fn(uint) -> T; |
| 3 | + |
1 | 4 | trait BaseIter<A> {
|
2 | 5 | pure fn each(blk: fn(A) -> bool);
|
3 | 6 | pure fn size_hint() -> option<uint>;
|
@@ -29,6 +32,26 @@ trait CopyableIter<A:copy> {
|
29 | 32 | pure fn find(p: fn(A) -> bool) -> option<A>;
|
30 | 33 | }
|
31 | 34 |
|
| 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 | + |
32 | 55 | pure fn eachi<A,IA:BaseIter<A>>(self: IA, blk: fn(uint, A) -> bool) {
|
33 | 56 | let mut i = 0u;
|
34 | 57 | for self.each |a| {
|
@@ -172,6 +195,105 @@ pure fn find<A: copy,IA:BaseIter<A>>(self: IA,
|
172 | 195 | return none;
|
173 | 196 | }
|
174 | 197 |
|
| 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 | + |
175 | 297 | /*
|
176 | 298 | #[test]
|
177 | 299 | fn test_enumerate() {
|
|
0 commit comments