Remove empty parameter list from iterator()
#520
Description
There was a discussion on https://gitter.im/scala/collection-strawman about whether or not IterableOnce.iterator()
/Iterable.iterator()
should have an empty parameter list, or none at all. I will do my best to record the main points of the discussion below.
(mostly quotes from Gitter)
I ask "Why does IterableOnce.iterator()
have an empty parameter list, rather than no parameter list?"
@szeiger and @julienrf suggest it is because iterator()
is a side-effecting method, in that two returned Iterator
s have distinct identities, so the method is not referentially transparent.
@martijnhoekstra notes that "If everything that's not referentially transparent is a side effect, obtaining an iterator is a side-effect".
I ask "What about toArray
? The Arrays are mutable, so while initially they would be equivalent, you could modify them so they are not".
@szeiger: "Indeed, if you go by referential transparency a lot more methods would need an empty argument list. What about size
? When used on a mutable collection it's not referentially transparent. Of course, nothing is. The distinction doesn't make any sense there. So what about List.size
? It is referentially transparent but that's not good enough because substituting such calls has huge performance implications. In a pure functional language the compiler can help you with that but Scala can't."
@SethTisue: "My intuition likes the 'initially they would be equivalent' side of your way of phrasing it, @NthPortal. But I'm having trouble backing up my intuition with a convincing argument [...] I think my intuition is something like, require the ()
if it introduces mutation or side effects into a program that wouldn't otherwise have it. And toArray
doesn't do that, because you are free to write code that uses Array
but never mutates an array".
@martijnhoekstra: "Neither does iterator()
though - provided you never call next()
[...] There is a lot less you can do with an iterator without modifying it than you can do with an Array
without modifying it though".
@SethTisue: "In Scala through 2.12, .iterator
has no parameter lists and the compiler says 'Iterator[...] does not take parameters' if you write .iterator()
. So somebody made a different decision on this years ago. Just leaving it like it was doesn't feel terrible to me. Even if you buy the argument that it ought to have the ()
, I'm not sure it's worth annoying people with the change, especially since (as Stefan has pointed out) the change will become more annoying when future Scala requires the ()
".
@Ichoran says that "My intuition is that ()
as a way to denote referential transparency is not a good idea anyway. Instead, ()
is useful as a marker for things that observably mutate the object on which the method is called. That is, for some method bar
, the behavior of x.bar
will be different after x.foo()
." @SethTisue likes this intuition.