Scala,扩展了迭代器

J P*_*lar 10 iterator scala lazy-evaluation extend enrich-my-library

我希望扩展迭代器来创建一个新方法takeWhileInclusive,它将像takeWhile最后一个元素一样运行.

我的问题是扩展迭代器以返回一个我希望延迟评估的新迭代器的最佳实践.来自C#背景我正常使用IEnumerable并使用yield关键字,但这样的选项似乎不存在于Scala中.

例如,我可以

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

所以在这种情况下,takeWhileInclusive只有解析值的谓词,直到我得到大于6的结果,并且它将包括第一个结果

到目前为止我有:

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

class IteratorExtension[T <: Any](i : Iterator[T]) {
  def takeWhileInclusive(predicate:(T) => Boolean) = ?
}
Run Code Online (Sandbox Code Playgroud)

Tra*_*own 11

你可以使用这种span方法Iterator很干净地做到这一点:

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._
Run Code Online (Sandbox Code Playgroud)

例如,现在(0 until 10).toIterator.takeWhileInclusive(_ < 4).toList给出List(0, 1, 2, 3, 4).


Rex*_*err 7

这是我发现可变解决方案优越的一个案例:

class InclusiveIterator[A](ia: Iterator[A]) {
  def takeWhileInclusive(p: A => Boolean) = {
    var done = false
    val p2 = (a: A) => !done && { if (!p(a)) done=true; true }
    ia.takeWhile(p2)
  }
}
implicit def iterator_can_include[A](ia: Iterator[A]) = new InclusiveIterator(ia)
Run Code Online (Sandbox Code Playgroud)