On Thu, Feb 13, 2014 at 10:05 AM, Simon Sapin <[email protected]> wrote:

> Proposal:
> 
> 0. An iterator is said to be "well-behaved" if, after its .next() method has
> returned None once, any subsequent call also returns None.
> 


I agree with the spirit of your proposal. But I would change that first clause 
above to read:

An iterator is said to be "well-behaved" when its .next() method always returns 
None if the iterator logically has no elements to iterate over.

And all iterators should, by convention, be well-behaved. Otherwise it's 
impossible to pinpoint what exactly is the bug in the following code:

struct Digits {
    n: int
}

impl Iterator<int> for Digits {
    fn next(&mut self) -> Option<int> {
        self.n += 1;

        if self.n == 10 {
            None
        }
        else {
            Some(self.n)
        }
    }
}

fn main() {
    let mut itr = Digits { n: -1 };

    for i in itr { // for-loop consumes all items in itr
        println!("{}", i);
    }

    let sum = itr.fold(0, |a, b| a + b); // Infinite loop
    println!("{}", sum);
}

Given the current std::iter::Iterator specification [1], the implementation of 
the .next() method of Digits is valid. Also, the fold method of Iterator trait 
should return the initial state (the first argument) when fold is called on an 
empty iterator, but the call get's stuck on an infinite loop instead.

[1]: The Iterator protocol states that an iterator yields a (potentially-empty, 
potentially-infinite) sequence of values, and returns None to signal that it's 
finished. The Iterator protocol does not define behavior after None is 
returned. A concrete Iterator implementation may choose to behave however it 
wishes, either by returning None infinitely, or by doing something else.


_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to