This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Contract of Iterator

8 replies
dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.

I wish to add to the ScalaDoc of Iterator a note to the effect that
calling any method that returns (another) Iterator will leave the old
Iterator in an undefined state, where behavior of further methods
calls is unspecified and subject to change without notice. The old
behavior should not be used anymore.

Typical "use case" I want to warn people off is:

val next10 = it.take(10).toList
val remaining = it.toList

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: Contract of Iterator

Am 18.09.2011 00:03, schrieb Daniel Sobral:
> I wish to add to the ScalaDoc of Iterator a note to the effect that
> calling any method that returns (another) Iterator will leave the old
> Iterator in an undefined state, where behavior of further methods
> calls is unspecified and subject to change without notice. The old
> behavior should not be used anymore.
>
> Typical "use case" I want to warn people off is:
>
> val next10 = it.take(10).toList
> val remaining = it.toList
>
+1, since i once stumbled over this

Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: Contract of Iterator

On 18/09/11 16:46, HamsterofDeath wrote:
> Am 18.09.2011 00:03, schrieb Daniel Sobral:
>> I wish to add to the ScalaDoc of Iterator a note to the effect that
>> calling any method that returns (another) Iterator will leave the old
>> Iterator in an undefined state, where behavior of further methods
>> calls is unspecified and subject to change without notice. The old
>> behavior should not be used anymore.
>>
>> Typical "use case" I want to warn people off is:
>>
>> val next10 = it.take(10).toList
>> val remaining = it.toList
>>
> +1, since i once stumbled over this
I'd like to do with it with types.

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: Contract of Iterator

Am 18.09.2011 08:49, schrieb Tony Morris:
> On 18/09/11 16:46, HamsterofDeath wrote:
>> Am 18.09.2011 00:03, schrieb Daniel Sobral:
>>> I wish to add to the ScalaDoc of Iterator a note to the effect that
>>> calling any method that returns (another) Iterator will leave the old
>>> Iterator in an undefined state, where behavior of further methods
>>> calls is unspecified and subject to change without notice. The old
>>> behavior should not be used anymore.
>>>
>>> Typical "use case" I want to warn people off is:
>>>
>>> val next10 = it.take(10).toList
>>> val remaining = it.toList
>>>
>> +1, since i once stumbled over this
> I'd like to do with it with types.
>
me too, but how can you change the type of an existing value from
"iterator" to "brokeniterator"?

Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: Contract of Iterator

On 18/09/11 20:01, HamsterofDeath wrote:
> Am 18.09.2011 08:49, schrieb Tony Morris:
>> On 18/09/11 16:46, HamsterofDeath wrote:
>>> Am 18.09.2011 00:03, schrieb Daniel Sobral:
>>>> I wish to add to the ScalaDoc of Iterator a note to the effect that
>>>> calling any method that returns (another) Iterator will leave the old
>>>> Iterator in an undefined state, where behavior of further methods
>>>> calls is unspecified and subject to change without notice. The old
>>>> behavior should not be used anymore.
>>>>
>>>> Typical "use case" I want to warn people off is:
>>>>
>>>> val next10 = it.take(10).toList
>>>> val remaining = it.toList
>>>>
>>> +1, since i once stumbled over this
>> I'd like to do with it with types.
>>
> me too, but how can you change the type of an existing value from
> "iterator" to "brokeniterator"?
trait SafeIterator[A] {
def next: STRef[A]
def hasNext: STRef[Boolean]
}

See Lazy Functional State Threads by Simon Peyton-Jones

Antoras
Joined: 2010-05-23,
User offline. Last seen 1 year 19 weeks ago.
Re: Contract of Iterator

On 09/18/2011 12:03 AM, Daniel Sobral wrote:
> I wish to add to the ScalaDoc of Iterator a note to the effect that
> calling any method that returns (another) Iterator will leave the old
> Iterator in an undefined state, where behavior of further methods
> calls is unspecified and subject to change without notice. The old
> behavior should not be used anymore.
>
> Typical "use case" I want to warn people off is:
>
> val next10 = it.take(10).toList
> val remaining = it.toList
Is there a reason why it is implemented this way? If I have a List, I
won't get an Iterator and if I always have an Iterator I won't get a
now one.

Methods like `take` and `grouped` produce always an Iterator and not
the type which is expected. They should only produce an Iterator when
they are called to an Iterator, but if so they create a new one. When I
really need an Iterator I wanna say this explicitly with
`list.iterator.take(n)`. This implicit behavior is unexpected (for me)
and I don't understand it. Can someone explain it?

Thanks,
Antoras

Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: Contract of Iterator

On 18/09/11 20:52, Antoras wrote:
> On 09/18/2011 12:03 AM, Daniel Sobral wrote:
>> I wish to add to the ScalaDoc of Iterator a note to the effect that
>> calling any method that returns (another) Iterator will leave the old
>> Iterator in an undefined state, where behavior of further methods
>> calls is unspecified and subject to change without notice. The old
>> behavior should not be used anymore.
>>
>> Typical "use case" I want to warn people off is:
>>
>> val next10 = it.take(10).toList
>> val remaining = it.toList
> Is there a reason why it is implemented this way? If I have a List, I
> won't get an Iterator and if I always have an Iterator I won't get a
> now one.
>
> Methods like `take` and `grouped` produce always an Iterator and not
> the type which is expected. They should only produce an Iterator when
> they are called to an Iterator, but if so they create a new one. When I
> really need an Iterator I wanna say this explicitly with
> `list.iterator.take(n)`. This implicit behavior is unexpected (for me)
> and I don't understand it. Can someone explain it?
>
> Thanks,
> Antoras
>

It is not possible to implement take (and others) on Iterator without
advancing that iterator making readability difficult and sketchy at
best. This is a problem in general with uncontrolled side-effects and is
not specific to Iterator. You get the same issue in other contexts with
uncontrolled side-effects.

Antoras
Joined: 2010-05-23,
User offline. Last seen 1 year 19 weeks ago.
Re: Contract of Iterator

On Sun 18 Sep 2011 01:43:36 PM CEST, Tony Morris wrote:
> On 18/09/11 20:52, Antoras wrote:
>> On 09/18/2011 12:03 AM, Daniel Sobral wrote:
>>> I wish to add to the ScalaDoc of Iterator a note to the effect that
>>> calling any method that returns (another) Iterator will leave the old
>>> Iterator in an undefined state, where behavior of further methods
>>> calls is unspecified and subject to change without notice. The old
>>> behavior should not be used anymore.
>>>
>>> Typical "use case" I want to warn people off is:
>>>
>>> val next10 = it.take(10).toList
>>> val remaining = it.toList
>> Is there a reason why it is implemented this way? If I have a List, I
>> won't get an Iterator and if I always have an Iterator I won't get a
>> now one.
>>
>> Methods like `take` and `grouped` produce always an Iterator and not
>> the type which is expected. They should only produce an Iterator when
>> they are called to an Iterator, but if so they create a new one. When I
>> really need an Iterator I wanna say this explicitly with
>> `list.iterator.take(n)`. This implicit behavior is unexpected (for me)
>> and I don't understand it. Can someone explain it?
>>
>> Thanks,
>> Antoras
>>
>
> It is not possible to implement take (and others) on Iterator without
> advancing that iterator making readability difficult and sketchy at
> best. This is a problem in general with uncontrolled side-effects and is
> not specific to Iterator. You get the same issue in other contexts with
> uncontrolled side-effects.
>
I don't fully accept this answer. I tried to implement such an Iterator
and I see now that it is more complicated. But that's only the case for
methods like `take`. The method `grouped` for example is easy to
implement. There is no need to return always an Iterator.

Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: Contract of Iterator

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 09/19/2011 03:54 AM, Antoras wrote:
>
>
> On Sun 18 Sep 2011 01:43:36 PM CEST, Tony Morris wrote:
>> On 18/09/11 20:52, Antoras wrote:
>>> On 09/18/2011 12:03 AM, Daniel Sobral wrote:
>>>> I wish to add to the ScalaDoc of Iterator a note to the effect that
>>>> calling any method that returns (another) Iterator will leave the old
>>>> Iterator in an undefined state, where behavior of further methods
>>>> calls is unspecified and subject to change without notice. The old
>>>> behavior should not be used anymore.
>>>>
>>>> Typical "use case" I want to warn people off is:
>>>>
>>>> val next10 = it.take(10).toList
>>>> val remaining = it.toList
>>> Is there a reason why it is implemented this way? If I have a List, I
>>> won't get an Iterator and if I always have an Iterator I won't get a
>>> now one.
>>>
>>> Methods like `take` and `grouped` produce always an Iterator and not
>>> the type which is expected. They should only produce an Iterator when
>>> they are called to an Iterator, but if so they create a new one. When I
>>> really need an Iterator I wanna say this explicitly with
>>> `list.iterator.take(n)`. This implicit behavior is unexpected (for me)
>>> and I don't understand it. Can someone explain it?
>>>
>>> Thanks,
>>> Antoras
>>>
>>
>> It is not possible to implement take (and others) on Iterator without
>> advancing that iterator making readability difficult and sketchy at
>> best. This is a problem in general with uncontrolled side-effects and is
>> not specific to Iterator. You get the same issue in other contexts with
>> uncontrolled side-effects.
>>
> I don't fully accept this answer. I tried to implement such an Iterator
> and I see now that it is more complicated. But that's only the case for
> methods like `take`. The method `grouped` for example is easy to
> implement. There is no need to return always an Iterator.

The ease of implementation is not the point. The point is that the
iterator advances when I call grouped, or depending on the
implementation, when I access the result of grouped. This causes havoc.
This havoc is not specific to iterator -- it arises in any uncontrolled
environment where the type system is not utilised to denote what is
really going on.

To be clear, any method (such as next or hasNext) that accepts no
arguments should always return the same result (a constant function).
Since this is not true for Iterator methods, this gives rise to havoc.
It is quite possible to return the same value from these methods without
losing functionality -- you just need a sufficiently equipped type
system. It turns out that Scala already has such a type system (see
scalaz.effects).

HTH

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland