Iterator(), next() and hasNext(). Why are they operator fun?


#1

https://kotlinlang.org/docs/reference/control-flow.html#for-loops

As mentioned before, for iterates through anything that provides an iterator, i.e.

  • has a member- or extension-function iterator() , whose return type
    • has a member- or extension-function next() , and
    • has a member- or extension-function hasNext() that returns Boolean .

All of these three functions need to be marked as operator .

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-iterable/index.html
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-iterator/index.html

abstract operator fun iterator(): Iterator<T>
abstract operator fun hasNext(): Boolean
abstract operator fun next(): T

I found that they must be operator fun and I tried to understand operators in Kotlin, but I can’t understand why. Is there any document how and when they’re interpreted as operator?
I don’t know, but maybe they’re treated as operator because they’re called without explicit function call statement, but it’s not easy to find about these things in documents.


#2

Yes! The key point is that there is a special syntax that will make use of these functions without a syntactically visible call. Without marking them as operator, the special syntax would not be available.


#3

Thanks for the explanation.
I’m not familiar with language design theory, so I don’t know if this is common philosophy of operators, but it would be better if the language document explicitly explains it because it explains operator overloadings and operator-thing in iterator which made me think it’s not explaining operator keyword fully.


#4

There is only a small set of function names that can be marked as operators in Kotlin. Once you have learned them, that’s it. Repeating how they work in the documentation of every instance of an operator function would be superfluous.


#5

I understand. But I was curious about why they are operator funs (I mean how they are interpreted and works in common way), rather than listing all or each of them.


#6

The reason why they need to be flagged as operator is probably just to make them more explicit. I don’t think there is a theoretical necessity to mark such functions as operators. Theoretically it could work as soon as the function name and signature matches the operator. In fact, afair methods defined in Java implicitly are treated as operators when their signatures match.


#7

I got it. I just thought there must be a rule about it, but maybe thinking about it was too much. Thanks for the opinion.


#8

In addition, maybe it has two other meaning:

At first, I think marking with ‘operator’ can avoid the calling which is treated as operators coincidently but you do not want , when the name of function is just same as syntax, so it need to be flagged explicitly with ‘operator’

Secondly, you can declare the operator function with extention function , rather than all in the class body; At this
time you can know that it is operator explicityly.

Additionly, the result of function ‘iterator’ do not need bo be inhertor of interface ‘Iterator’, and it could work as soon as the result has two function which matches the operator . you can see the demo below:

    class A {

        private var i = 0

        operator fun hasNext() = i < 10

        operator fun next() = i++
    }

    operator fun A.iterator() = this


    fun foo(){

        for(i in A()) print(i)
    }

#9

In fact, It also used to work that way for Kotlin functions. That was changed back in 2015:

This has been debated a lot in the past, and we finally decided that we want to introduce some more discipline into how operator overloading and infix function calls work in Kotlin. At the moment any function named plus that can be called as a.plus(b) can also be called as a + b . We will require such functions to be marked with the operator modifier, otherwise the operator notation will not be available for them. This makes operator use more disciplined and eliminates the possibility of random punctuation creeping into APIs. The most common example would be having a method called get but totally not intending it for use as square brackets.


#10

I believe in Java, classes are eligible to for-each loops when they implement Iterable


#11

I was talking about Java classes that are used in Kotlin code.