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