如何在不使用可变变量的情况下在scala中编写迭代器?

如何在不使用可变变量的情况下在scala中编写迭代器?,scala,functional-programming,iterator,Scala,Functional Programming,Iterator,我想实现迭代器特性,但要以函数方式实现,即不使用变量。如何实现 假设我有一个外部库,通过调用函数getNextElements(numOfElements:Int):Array[String]获取一些元素,我想使用该函数实现一个迭代器,但不使用指示“当前”数组的变量(在我的例子中是var缓冲区)。我如何以功能性的方式实现这一点 class MyIterator[T](fillBuffer: Int => Array[T]) extends Iterator[T] { var buf

我想实现迭代器特性,但要以函数方式实现,即不使用变量。如何实现

假设我有一个外部库,通过调用函数
getNextElements(numOfElements:Int):Array[String]
获取一些元素,我想使用该函数实现一个迭代器,但不使用指示“当前”数组的变量(在我的例子中是var缓冲区)。我如何以功能性的方式实现这一点

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)
}

迭代器是可变的,至少在没有同时返回状态变量的接口的情况下是可变的,因此一般来说,如果没有某种变异,就不能直接实现接口

这就是说,
迭代器
伴随对象中有一些非常有用的函数,可以让您隐藏变异,并使实现更清晰。我会实现你的一些东西,比如:

Iterator.continually(getNextElements(10)).flatten
每当需要填充缓冲区时,就会调用
getNextElements(10)
flatten
将其从
迭代器[Array[A]]
更改为
迭代器[A]

注意,这将返回一个无限迭代器。您的问题没有提到检测源元素的结尾,但我通常会使用
takeWhile
实现它。例如,如果
getNextElements
在没有更多元素时返回空数组,则可以执行以下操作:

 Iterator.continually(getNextElements(10)).takeWhile(!_.isEmpty).flatten

另一种选择是使用流(或懒散列表)而不是迭代器,前者可以是纯迭代器。但是,由于基于状态的循环和递归在表达能力上被证明是等价的,我假设至少有一种理论上的可能性,可以使用递归来实现它。如果我错了,请纠正我。