Reputation: 557
Given a class from a legacy library that behaves like an Iterator
such that you can traverse it's content with hasNext
and next
but it does not implement the Iterator
interface:
class LegacyIterator[T](iterable: Iterable[T]) {
val iterator: Iterator[T] = iterable.iterator
def hasNext: Boolean = iterator.hasNext
def next(): T = iterator.next()
}
val lagIter: LegacyIterator[Int] = new LegacyIterator(List(1, 2, 3))
What would be your opinion on the most elegant way to traverse such a data structure - idially inside the scope of the function? I've come up with two versions:
One using @tailrec
@tailrec
def lagIterList(accu: List[Int]): List[Int] =
if (lagIter.hasNext) lagIterList(lagIter.next() :: accu) else accu
val res = lagIterList(Nil).reverse
And one using LazyList
def ll: LazyList[Int] = if(lagIter.hasNext) lagIter.next() #:: ll else LazyList.empty
val res = ll.toList
What would you think would be more Scala idiomatic? The tailrec
version is probably slightly faster on larger data structures but the LazyList
version makes better use of the collections library.
Or any other ideas?
Upvotes: 0
Views: 96
Reputation: 22895
Well, it depends on what you mean by "traverse it".
If you only mean, creating a List
out of it, I would just use unfold
def toList[T](iter: LegacyIterator[T]): List[T] =
List.unfold(()) { _ =>
Option.when(iter.hasNext()) {
iter.next() -> ()
}
}
Upvotes: 1
Reputation: 40510
Just convert it into a normal iterator:
val normalIterator = Iterator.continually(legacyIterator)
.takeWhile(_.hasNext)
.map(_.next)
Then you can use any of the regular scala tooling to traverse/transform it, e.g.: val list = normalIterator.toList
Upvotes: 2
Reputation: 26084
I would consider an implicit wrapper class extending Iterator[T]:
implicit class LegacyIteratorWrapper[T](private val underlying: LegacyIterator[T]) extends Iterator[T] {
override def hasNext: Boolean = underlying.hasNext
override def next(): T = underlying.next()
}
val lagIter: LegacyIterator[Int] = new LegacyIterator(List(1, 2, 3))
// traversal
for (elem <- lagIter) println(elem)
// conversion to list
val lagIterList = lagIter.toList
Upvotes: 2