Operator fun iterator


#1

It can be overkill, but maybe it’s an idea to let a class which has the function operator fun iterator call functions of a sequence?

//an external class
final class Foo
operator fun Foo.iterator() = ...

//usage:    
foo.forEach{}  // maps to: foo.iterator().foreach{}
foo.map{}.first() // maps to: foo.iterator().map().first()

#2

Why not simply let Foo implement Iterable?


#3

Because Foo already exists and is out of control
I found this funny as I never use the normal for-loop anymore and I knew that you could do for with the operator.
I found it strange when for is allowed, but forEach wasn’t. The next step would be to add map and so everything of sequence.


#4

The problem with allowing this is that the implementation of this would be kinda strange. I mean most functions of Iterable you want to use are extensions, therefor you have to somehow cast your object into an iterable or wrap it (which might be bad for performance?). Otherwise you would need create copies of the functions you call using your type instead of Iterable which definitely is a bad idea as it might not always work and would create a lot of unnecessary byte code.

I think a better way to solve this in the future is to maybe add a warning (or idea intention) warning if a class has the iterator function but does not implement Iterable.
This still won’t fix your usecase, but maybe you can create an issue on the project your using.

Also I don’t think Kotlin should encourage leaving out the Iterable interface.


#5

@tieskedh @Wasabi375 Both have valid points. The proposal could work if the operator would return an Iterable (or Sequence) with the appropriate name.
Alternatively what about the following:

final class Foo
fun Foo.iterator() = ...

private class MakeSequence<T>(val receiver: T, val iterator: T.() -> Iterator<T>) {
    override operator fun iterator(): Iterator<T> = receiver.iterator()
}

fun <T> T.makeSequence(iteratorFactory: T.() -> Iterator<T>) 
    = MakeSequence(this, iteratorFactory)

foo.makeSequence { iterator() }
   .forEach { println("Hello Foo") }

This can be done at library level. At language level some support could be useful. Note that the above would be required to correctly handle your proposed system anyway.

Also you can just provide an extension T.asSequence() to have “transparent” support for sequences (T.asList(), T.asCollection(),… etc.)