On 04 Mar 2014, at 15:59, Simon Sapin <simon.sa...@exyr.org> wrote:

> On 04/03/2014 13:23, Tommi wrote:
>> On Thu, Feb 13, 2014 at 10:05 AM, Simon Sapin <simon.sa...@exyr.org
>> <mailto:simon.sa...@exyr.org>> 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./
> 
> "No elements to iterate over" is already what None is supposed to mean, so 
> this doesn’t add anything.

What the wording of my definition does is it relaxes the constraints your 
definition specified. This relaxation of the rule is needed because there might 
be a need for the use case of having a once empty iterator become non-empty 
again.


>> 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)
>>        }
>>    }
>> }
> 
> I don’t see what’s unclear here. This is the canonical example of an 
> ill-behaved iterator. This code is buggy, `self.n` should only be incremented 
> when returning Some().

I agree that this should be an ill-behaved iterator, but my point is that 
according to the specification [1], this is _not_ an ill-behaved iterator, it's 
a completely valid one. Given that self.n is less than 10, it correctly returns 
some elements as Some(...) and then it returns None. After it has returned 
None, according to specification [1], it is allowed to return whatever it 
wants. Therefore I'd be inclined to say that the bug in my example is in 
calling fold on an iterator whose all elements have been exhausted, but that 
seems just silly and fragile.

[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
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to