Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does a Stream need to be lazy?

The following are both meant to create a Stream of integers:

val s: Stream[Int] = 1 #:: s.map(_ + 1)

def makeStream = {
  val s: Stream[Int] = 1 #:: s.map(_ + 1)
  s
}

The first is fine; however the makeStream method won't compile:

error: forward reference extends over definition of value s
  val s: Stream[Int] = 1 #:: s.map(_ + 1)
                             ^

It only compiles if we make s a lazy val. Why does it need to be a lazy val in a method, but not outside?

like image 261
Luigi Plinge Avatar asked Aug 05 '11 21:08

Luigi Plinge


People also ask

What does it mean that stream is lazy?

Streams are lazy because intermediate operations are not evaluated until terminal operation is invoked. Each intermediate operation creates a new stream, stores the provided operation/function and return the new stream.

Are streams better than for loops?

If you have a small list, loops perform better. If you have a huge list, a parallel stream will perform better. Purely thinking in terms of performance, you shouldn't use a for-each loop with an ArrayList, as it creates an extra Iterator instance that you don't need (for LinkedList it's a different matter).

Why steam is lazy loading?

How Stream is lazy? It is an important characteristic of streams because the operation on the source data is only performed when the terminal operation is initiated. It doesn't consume the source elements as in eager loading, the source elements are consumed only on demand. only.

Are streams slower than for loops?

Yes, streams are sometimes slower than loops, but they can also be equally fast; it depends on the circumstances. The point to take home is that sequential streams are no faster than loops.


1 Answers

Inside a class, a val definition decompiles into an "getter" method that references a hidden class field. These "getter" methods can be self-referential (or rather, the class initializer can reference the "getter") because this is the semantics of Java methods. Note that your "outside" definition of val s is actually wrapped in a hidden class by the REPL (this is how the REPL circumvents the restriction that a val can't be declared at the top level).

Inside a method, the val definition does not decompile into a "getter" method, but rather into the bytecode necessary to generate a value on the stack. A lazy val, on the other hand, always requires a "getter" method which, as such, can be self-referential.

like image 194
Kipton Barros Avatar answered Oct 25 '22 17:10

Kipton Barros