@@ -18,8 +18,7 @@ use either;
1818use iterator:: Iterator ;
1919use option:: { None , Option , Some , OptionIterator } ;
2020use vec;
21- use vec:: { OwnedVector , ImmutableVector } ;
22- use container:: Container ;
21+ use vec:: OwnedVector ;
2322use to_str:: ToStr ;
2423use str:: StrSlice ;
2524
@@ -269,86 +268,76 @@ pub fn map_opt<T, U: ToStr, V>(o_t: &Option<T>,
269268 }
270269}
271270
272- // FIXME: #8228 Replaceable by an external iterator?
273- /// Maps each element in the vector `ts` using the operation `op`. Should an
274- /// error occur, no further mappings are performed and the error is returned.
275- /// Should no error occur, a vector containing the result of each map is
276- /// returned.
271+ /// Takes each element in the iterator: if it is an error, no further
272+ /// elements are taken, and the error is returned.
273+ /// Should no error occur, a vector containing the values of each Result
274+ /// is returned.
277275///
278276/// Here is an example which increments every integer in a vector,
279277/// checking for overflow:
280278///
281- /// fn inc_conditionally(x: uint) -> result <uint,str> {
279+ /// fn inc_conditionally(x: uint) -> Result <uint, &'static str> {
282280/// if x == uint::max_value { return Err("overflow"); }
283281/// else { return Ok(x+1u); }
284282/// }
285- /// map(~ [1u, 2u, 3u], inc_conditionally).chain {|incd|
286- /// assert!(incd == ~[2u, 3u, 4u] );
287- /// }
283+ /// let v = [1u, 2, 3];
284+ /// let res = collect(v.iter().map(|&x| inc_conditionally(x)) );
285+ /// assert!(res == Ok(~[2u, 3, 4]));
288286#[ inline]
289- pub fn map_vec < T , U , V > ( ts : & [ T ] , op : & fn ( & T ) -> Result < V , U > )
290- -> Result < ~[ V ] , U > {
291- let mut vs: ~[ V ] = vec:: with_capacity ( ts. len ( ) ) ;
292- for t in ts. iter ( ) {
293- match op ( t) {
294- Ok ( v) => vs. push ( v) ,
295- Err ( u) => return Err ( u)
287+ pub fn collect < T , E , Iter : Iterator < Result < T , E > > > ( mut iterator : Iter )
288+ -> Result < ~[ T ] , E > {
289+ let ( lower, _) = iterator. size_hint ( ) ;
290+ let mut vs: ~[ T ] = vec:: with_capacity ( lower) ;
291+ for t in iterator {
292+ match t {
293+ Ok ( v) => vs. push ( v) ,
294+ Err ( u) => return Err ( u)
296295 }
297296 }
298- return Ok ( vs) ;
297+ Ok ( vs)
299298}
300299
301- // FIXME: #8228 Replaceable by an external iterator?
302- /// Same as map, but it operates over two parallel vectors.
300+ /// Perform a fold operation over the result values from an iterator.
303301///
304- /// A precondition is used here to ensure that the vectors are the same
305- /// length. While we do not often use preconditions in the standard
306- /// library, a precondition is used here because result::t is generally
307- /// used in 'careful' code contexts where it is both appropriate and easy
308- /// to accommodate an error like the vectors being of different lengths.
302+ /// If an `Err` is encountered, it is immediately returned.
303+ /// Otherwise, the folded value is returned.
309304#[ inline]
310- pub fn map_vec2 < S , T , U : ToStr , V > ( ss : & [ S ] , ts : & [ T ] ,
311- op : & fn ( & S , & T ) -> Result < V , U > ) -> Result < ~ [ V ] , U > {
312- assert ! ( vec :: same_length ( ss , ts ) ) ;
313- let n = ts . len ( ) ;
314- let mut vs = vec :: with_capacity ( n ) ;
315- let mut i = 0 u ;
316- while i < n {
317- match op ( & ss [ i ] , & ts [ i ] ) {
318- Ok ( v) => vs . push ( v) ,
319- Err ( u) => return Err ( u)
305+ pub fn fold < T , V , E ,
306+ Iter : Iterator < Result < T , E > > > (
307+ mut iterator : Iter ,
308+ mut init : V ,
309+ f : & fn ( V , T ) -> V )
310+ -> Result < V , E > {
311+ for t in iterator {
312+ match t {
313+ Ok ( v) => init = f ( init , v) ,
314+ Err ( u) => return Err ( u)
320315 }
321- i += 1 u;
322316 }
323- return Ok ( vs ) ;
317+ Ok ( init )
324318}
325319
326- // FIXME: #8228 Replaceable by an external iterator?
327- /// Applies op to the pairwise elements from `ss` and `ts`, aborting on
328- /// error. This could be implemented using `map_zip()` but it is more efficient
329- /// on its own as no result vector is built.
320+ /// Perform a trivial fold operation over the result values
321+ /// from an iterator.
322+ ///
323+ /// If an `Err` is encountered, it is immediately returned.
324+ /// Otherwise, a simple `Ok(())` is returned.
330325#[ inline]
331- pub fn iter_vec2 < S , T , U : ToStr > ( ss : & [ S ] , ts : & [ T ] ,
332- op : & fn ( & S , & T ) -> Result < ( ) , U > ) -> Result < ( ) , U > {
333- assert ! ( vec:: same_length( ss, ts) ) ;
334- let n = ts. len ( ) ;
335- let mut i = 0 u;
336- while i < n {
337- match op ( & ss[ i] , & ts[ i] ) {
338- Ok ( ( ) ) => ( ) ,
339- Err ( u) => return Err ( u)
340- }
341- i += 1 u;
342- }
343- return Ok ( ( ) ) ;
326+ pub fn fold_ < T , E , Iter : Iterator < Result < T , E > > > (
327+ iterator : Iter )
328+ -> Result < ( ) , E > {
329+ fold ( iterator, ( ) , |_, _| ( ) )
344330}
345331
332+
346333#[ cfg( test) ]
347334mod tests {
348335 use super :: * ;
349336
350337 use either;
338+ use iterator:: range;
351339 use str:: OwnedStr ;
340+ use vec:: ImmutableVector ;
352341
353342 pub fn op1 ( ) -> Result < int , ~str > { Ok ( 666 ) }
354343
@@ -431,4 +420,44 @@ mod tests {
431420 assert_eq ! ( r. to_either( ) , either:: Right ( 100 ) ) ;
432421 assert_eq ! ( err. to_either( ) , either:: Left ( 404 ) ) ;
433422 }
423+
424+ #[ test]
425+ fn test_collect ( ) {
426+ assert_eq ! ( collect( range( 0 , 0 )
427+ . map( |_| Ok :: <int, ( ) >( 0 ) ) ) ,
428+ Ok ( ~[ ] ) ) ;
429+ assert_eq ! ( collect( range( 0 , 3 )
430+ . map( |x| Ok :: <int, ( ) >( x) ) ) ,
431+ Ok ( ~[ 0 , 1 , 2 ] ) ) ;
432+ assert_eq ! ( collect( range( 0 , 3 )
433+ . map( |x| if x > 1 { Err ( x) } else { Ok ( x) } ) ) ,
434+ Err ( 2 ) ) ;
435+
436+ // test that it does not take more elements than it needs
437+ let functions = [ || Ok ( ( ) ) , || Err ( 1 ) , || fail ! ( ) ] ;
438+
439+ assert_eq ! ( collect( functions. iter( ) . map( |f| ( * f) ( ) ) ) ,
440+ Err ( 1 ) ) ;
441+ }
442+
443+ #[ test]
444+ fn test_fold ( ) {
445+ assert_eq ! ( fold_( range( 0 , 0 )
446+ . map( |_| Ok :: <( ) , ( ) >( ( ) ) ) ) ,
447+ Ok ( ( ) ) ) ;
448+ assert_eq ! ( fold( range( 0 , 3 )
449+ . map( |x| Ok :: <int, ( ) >( x) ) ,
450+ 0 , |a, b| a + b) ,
451+ Ok ( 3 ) ) ;
452+ assert_eq ! ( fold_( range( 0 , 3 )
453+ . map( |x| if x > 1 { Err ( x) } else { Ok ( ( ) ) } ) ) ,
454+ Err ( 2 ) ) ;
455+
456+ // test that it does not take more elements than it needs
457+ let functions = [ || Ok ( ( ) ) , || Err ( 1 ) , || fail ! ( ) ] ;
458+
459+ assert_eq ! ( fold_( functions. iter( )
460+ . map( |f| ( * f) ( ) ) ) ,
461+ Err ( 1 ) ) ;
462+ }
434463}
0 commit comments