Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala, extending the iterator

Im looking to extended the iterator to create a new method takeWhileInclusive, which will operate like takeWhile but include the last element.

My issue is what is best practice to extend the iterator to return a new iterator which I would like to be lazy evaluated. Coming from a C# background I normal use IEnumerable and use the yield keyword, but such an option doesn't appear to exist in Scala.

for example I could have

List(0,1,2,3,4,5,6,7).iterator.map(complex time consuming algorithm).takeWhileInclusive(_ < 6)

so in this case the takeWhileInclusive would only have resolve the predicate on the values until I get the a result greater than 6, and it will include this first result

so far I have:

object ImplicitIterator {
  implicit def extendIterator(i : Iterator[Any]) = new IteratorExtension(i)
}

class IteratorExtension[T <: Any](i : Iterator[T]) {
  def takeWhileInclusive(predicate:(T) => Boolean) = ?
}
like image 562
J Pullar Avatar asked Feb 17 '12 14:02

J Pullar


1 Answers

You can use the span method of Iterator to do this pretty cleanly:

class IteratorExtension[A](i : Iterator[A]) {
  def takeWhileInclusive(p: A => Boolean) = {
    val (a, b) = i.span(p)
    a ++ (if (b.hasNext) Some(b.next) else None)
  }
}

object ImplicitIterator {
  implicit def extendIterator[A](i : Iterator[A]) = new IteratorExtension(i)
}

import ImplicitIterator._

Now (0 until 10).toIterator.takeWhileInclusive(_ < 4).toList gives List(0, 1, 2, 3, 4), for example.

like image 82
Travis Brown Avatar answered Sep 27 '22 19:09

Travis Brown