Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use lazy values in Scala?

Tags:

java

jvm

scala

Why Scala introduces lazy parameters. Shouldn't it be managed by the JVM (invisible for the user) how the value is initialized? What is the real world use case in which it is worth to give the control into developers hand and define values as lazy?

like image 644
Łukasz Rzeszotarski Avatar asked Nov 13 '13 14:11

Łukasz Rzeszotarski


People also ask

What is the use of lazy in Scala?

Scala provides a nice language feature called lazy val that defers the initialization of a variable. The lazy initialization pattern is common in Java programs. Though it seems tempting, the concrete implementation of lazy val has some subtle issues.

Does Scala use lazy evaluation?

Lazy Evaluation in ScalaHaskell is a functional programming language that uses lazy evaluation by default.

What is lazy loading in Scala?

Lazy evaluation or call-by-need is a evaluation strategy where an expression isn't evaluated until its first use i.e to postpone the evaluation till its demanded.

What is difference between Val and VAR in Scala?

The difference between val and var is that val makes a variable immutable — like final in Java — and var makes a variable mutable. Because val fields can't vary, some people refer to them as values rather than variables.


2 Answers

The by-name parameters: one of the primary motivations was to support dsls. They allow you to have a really nice syntax in APIs, that almost feel as if they're built into the language. For example, you can very easily define your own custom repeat-loop:

def repeat(body: =>Unit)(until: =>Boolean): Unit = {
  body
  if (until) {} else repeat(body)(until)
}

And then use it as if it were a part of the language.

var i = 0
repeat {
  println(i)
  i += 1
} (i < 3)

Or you could similarly spawn a new thread like this: spawn { println("on the new thread!") }, or you could do automatic resource management of your FileInputStreams like this: withFile("/home/john/.bashrc") { println(_.contents) }.

The lazy values - the motivations here are:

  1. lazy data-structures like Streams that are popular in functional languages that you can use to implement efficient data-structure a-la Okasaki's functional queues.
  2. to avoid allocating or initializing some expensive resources if they're never used in some object, e.g. file handles or database connections.
  3. to initialize objects fields in the correct order, for objects composed of many mixins.
  4. to achieve a correct "initialize only once" semantics when there are many threads sharing a single value (see introduction here).
  5. to have a translation scheme for nested singleton objects:

class A { object B }

becomes something like:

class A {
  class A$B$
  lazy val B = new A$B$
}
like image 58
axel22 Avatar answered Sep 22 '22 09:09

axel22


One common scenario is when the writer of a class does not know whether an expensive-to-initialize val will be used. In this case, the val is initialized on demand.

Another scenario is to organically control sequencing of initialization. Often an object is created long before a particular val can be initialized, because other classes haven't been initialized yet. In this case, laziness provides a convenient way for this sequencing to occur naturally, without the author coming up with a Master Plan that sequences a complex, multiphase initialization.

like image 22
Ed Staub Avatar answered Sep 24 '22 09:09

Ed Staub