Assume we have a side-effecting "producer" function f: () => Option[T]
which returns a Some
when repeatedly called until a future point at which it will forever return None
. (e.g. a wrapped Java API producing null
at EOF might well have this sort of behaviour).
Is it possible to wrap this function into something like a TraversableOnce
or an Iterator
, with the following constraints:
Stream
is not wantedvar
There are some useful methods on the Iterator
object, but nothing that exactly matches my use case. Any ideas welcome!
An iterator is a way to access elements of a collection one-by-one. It resembles to a collection in terms of syntax but works differently in terms of functionality. An iterator defined for any collection does not load the entire collection into the memory but loads elements one after the other.
Unlike operations directly on a concrete collection like List , operations on Iterator are lazy. A lazy operation does not immediately compute all of its results.
This does the trick:
def wrap[T](f: () => Option[T]): Iterator[T] = {
Iterator.continually(f()).takeWhile(_.isDefined).flatten
}
REPL test:
scala> :paste
// Entering paste mode (ctrl-D to finish)
var i = 0
def sideEffectingFunc(): Option[Int] = {
i += 1
if (i < 10) Some(i)
else None
}
// Exiting paste mode, now interpreting.
i: Int = 0
sideEffectingFunc: ()Option[Int]
scala> val it = wrap(sideEffectingFunc)
it: Iterator[Int] = non-empty iterator
scala> it.toList
res1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With