Scala view filter not lazy?

While trying to understand the differences between streams, iterators, and collection views, I came across the following strange behavior.

Here is the code (the card and the filter simply print their input and forward without changes):

object ArrayViewTest {
  def main(args: Array[String]) {
    val array = Array.range(1,10)

    print("stream-map-head: ")
    array.toStream.map(x => {print(x); x}).head

    print("\nstream-filter-head: ")
    array.toStream.filter(x => {print(x); true}).head

    print("\niterator-map-head: ")
    array.iterator.map(x => {print(x); x}).take(1).toArray

    print("\niterator-filter-head: ")
    array.iterator.filter(x => {print(x); true}).take(1).toArray

    print("\nview-map-head: ")
    array.view.map(x => {print(x); x}).head

    print("\nview-filter-head: ")
    array.view.filter(x => {print(x); true}).head
  }
}

And his conclusion:

stream-map-head: 1
stream-filter-head: 1
iterator-map-head: 1
iterator-filter-head: 1
view-map-head: 1
view-filter-head: 123456789    // <------ WHY ?

Why does the filter invoke the process of viewing the entire array? I expected that the filter evaluation is controlled only once, causing the head, as in all other cases, in particular, the same as when using the card in sight.

What insight am I missing?

(question about the mini-side for comment, why there is no head on the iterator?)

( scala.Array.range(1,10)) scala.collection.mutable.ArraySeq.range(1,10), scala.collection.mutable.ArrayBuffer.range(1,10) scala.collection.mutable.StringBuilder.newBuilder.append("123456789"). , , 1.

+4
2

, head isEmpty

trait IndexedSeqOptimized[+A, +Repr] extends Any with IndexedSeqLike[A, Repr] { self =>
...
override /*IterableLike*/
def head: A = if (isEmpty) super.head else this(0)

isEmpty length

trait IndexedSeqOptimized[+A, +Repr] extends Any with IndexedSeqLike[A, Repr] { self =>
  ...
  override /*IterableLike*/
  def isEmpty: Boolean = { length == 0 }

length Filtered,

trait Filtered extends super.Filtered with Transformed[A] {
  protected[this] lazy val index = {
    var len = 0
    val arr = new Array[Int](self.length)
    for (i <- 0 until self.length)
      if (pred(self(i))) {
        arr(len) = i
        len += 1
      }
    arr take len
  }
  def length = index.length
  def apply(idx: Int) = self(index(idx))
}

Filtered filter

protected override def newFiltered(p: A => Boolean): Transformed[A] =
 new { val pred = p } with AbstractTransformed[A] with Filtered

filter, map

+3

, , Array - . :) , , , . , - i- , , . - , , head. scala, .

-, , head , , head , , n , , . , .

+3

All Articles