3

I want to implement the iterator trait but in the functional way, ie, without using a var. How to do that?

Suppose I have an external library where I get some elements by calling a function getNextElements(numOfElements: Int):Array[String] and I want to implement an Iterator using that function but without using a variable indicating the "current" array (in my case, the var buffer). How can I implement that in the functional way?

class MyIterator[T](fillBuffer: Int => Array[T]) extends Iterator[T] {
    var buffer: List[T] = fillBuffer(10).toList

    override def hasNext(): Boolean = {
        if (buffer.isEmpty) buffer = fillBuffer(10).toList
        buffer.nonEmpty
    }

    override def next(): T = {
        if (!hasNext()) throw new NoSuchElementException()

        val elem: T = buffer.head
        buffer = buffer.tail
        elem
    }
}

class Main extends App {
    def getNextElements(num: Int): Array[String] = ???

    val iterator = new MyIterator[String](getNextElements)

    iterator.foreach(println)
}

1 Answer 1

4

Iterators are mutable, at least without an interface that also returns a state variable, so you can't in general implement the interface directly without some sort of mutation.

That being said, there are some very useful functions in the Iterator companion object that let you hide the mutation, and make the implementation cleaner. I would implement yours something like:

Iterator.continually(getNextElements(10)).flatten

This calls getNextElements(10) whenever it needs to fill the buffer. The flatten changes it from an Iterator[Array[A]] to an Iterator[A].

Note this returns an infinite iterator. Your question didn't say anything about detecting the end of your source elements, but I would usually implement that using takeWhile. For example, if getNextElements returns an empty array when there are no more elements, you can do:

 Iterator.continually(getNextElements(10)).takeWhile(!_.isEmpty).flatten
Sign up to request clarification or add additional context in comments.

2 Comments

Other alternative would be to use a Stream (or a LazyList) instead of an Iterator, which the first one can be pure.
I'm in no way familiar with the iterator interface. But since state based looping and recursion are proven to be equivalent in their expressive power, I'd assume that there is at least a theoretical possibility to implement it using nothing but recursion. Correct me if I'm wrong though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.