@@ -41,6 +41,13 @@ pub trait Extendable<A>: FromIterator<A> {
4141/// An interface for dealing with "external iterators". These types of iterators
4242/// can be resumed at any time as all state is stored internally as opposed to
4343/// being located on the call stack.
44+ ///
45+ /// The Iterator protocol states that an iterator yields a (potentially-empty,
46+ /// potentially-infinite) sequence of values, and returns `None` to signal that
47+ /// it's finished. The Iterator protocol does not define behavior after `None`
48+ /// is returned. A concrete Iterator implementation may choose to behave however
49+ /// it wishes, either by returning `None` infinitely, or by doing something
50+ /// else.
4451pub trait Iterator < A > {
4552 /// Advance the iterator and return the next value. Return `None` when the end is reached.
4653 fn next ( & mut self ) -> Option < A > ;
@@ -300,6 +307,36 @@ pub trait Iterator<A> {
300307 FlatMap { iter : self , f : f, frontiter : None , backiter : None }
301308 }
302309
310+ /// Creates an iterator that yields `None` forever after the underlying
311+ /// iterator yields `None`. Random-access iterator behavior is not
312+ /// affected, only single and double-ended iterator behavior.
313+ ///
314+ /// # Example
315+ ///
316+ /// ~~~ {.rust}
317+ /// fn process<U: Iterator<int>>(it: U) -> int {
318+ /// let mut it = it.fuse();
319+ /// let mut sum = 0;
320+ /// for x in it {
321+ /// if x > 5 {
322+ /// break;
323+ /// }
324+ /// sum += x;
325+ /// }
326+ /// // did we exhaust the iterator?
327+ /// if it.next().is_none() {
328+ /// sum += 1000;
329+ /// }
330+ /// sum
331+ /// }
332+ /// let x = ~[1,2,3,7,8,9];
333+ /// assert_eq!(process(x.move_iter()), 1006);
334+ /// ~~~
335+ #[ inline]
336+ fn fuse ( self ) -> Fuse < Self > {
337+ Fuse { iter : self , done : false }
338+ }
339+
303340 /// Creates an iterator that calls a function with a reference to each
304341 /// element before yielding it. This is often useful for debugging an
305342 /// iterator pipeline.
@@ -1421,6 +1458,79 @@ impl<'self,
14211458 }
14221459}
14231460
1461+ /// An iterator that yields `None` forever after the underlying iterator
1462+ /// yields `None` once.
1463+ #[ deriving( Clone , DeepClone ) ]
1464+ pub struct Fuse < T > {
1465+ priv iter : T ,
1466+ priv done : bool
1467+ }
1468+
1469+ impl < A , T : Iterator < A > > Iterator < A > for Fuse < T > {
1470+ #[ inline]
1471+ fn next ( & mut self ) -> Option < A > {
1472+ if self . done {
1473+ None
1474+ } else {
1475+ match self . iter . next ( ) {
1476+ None => {
1477+ self . done = true ;
1478+ None
1479+ }
1480+ x => x
1481+ }
1482+ }
1483+ }
1484+
1485+ #[ inline]
1486+ fn size_hint ( & self ) -> ( uint , Option < uint > ) {
1487+ if self . done {
1488+ ( 0 , Some ( 0 ) )
1489+ } else {
1490+ self . iter . size_hint ( )
1491+ }
1492+ }
1493+ }
1494+
1495+ impl < A , T : DoubleEndedIterator < A > > DoubleEndedIterator < A > for Fuse < T > {
1496+ #[ inline]
1497+ fn next_back ( & mut self ) -> Option < A > {
1498+ if self . done {
1499+ None
1500+ } else {
1501+ match self . iter . next_back ( ) {
1502+ None => {
1503+ self . done = true ;
1504+ None
1505+ }
1506+ x => x
1507+ }
1508+ }
1509+ }
1510+ }
1511+
1512+ // Allow RandomAccessIterators to be fused without affecting random-access behavior
1513+ impl < A , T : RandomAccessIterator < A > > RandomAccessIterator < A > for Fuse < T > {
1514+ #[ inline]
1515+ fn indexable ( & self ) -> uint {
1516+ self . iter . indexable ( )
1517+ }
1518+
1519+ #[ inline]
1520+ fn idx ( & self , index : uint ) -> Option < A > {
1521+ self . iter . idx ( index)
1522+ }
1523+ }
1524+
1525+ impl < T > Fuse < T > {
1526+ /// Resets the fuse such that the next call to .next() or .next_back() will
1527+ /// call the underlying iterator again even if it prevously returned None.
1528+ #[ inline]
1529+ fn reset_fuse ( & mut self ) {
1530+ self . done = false
1531+ }
1532+ }
1533+
14241534/// An iterator that calls a function with a reference to each
14251535/// element before yielding it.
14261536pub struct Inspect < ' self , A , T > {
0 commit comments