Lazy val and Infinite Sequences in Scala
Vals and Lazy vals are present in Scala. lazy keyword changes the val to get lazily initialized. Lazy initialization means that whenever an object creation seems expensive, the lazy keyword can be stick before val. This gives it the advantage to get initialized in the first use i.e. the expression inbound is not evaluated immediately but once on the first access.
Example:
// Scala program of Lazy val // Creating object object GFG { // Main method def main(args : Array[String]) { lazy val geek = { println ( "Initialization for the first time" ) 12 } // Part 1 println(geek) // Part 2 print(geek) } } |
Output :
Initialization for the first time 12 12
In the code above ‘geek’ was a lazy val and so for the first when it is accessed, it returned
Initialization for the first time 12
But for the second time when it is printed, it only returned
12
because it is a cached result.
When we use lazy keyword before a val keyword, a block expression is used to initialize the variable – “geek”. For using the block in Scala, the sequence of expressions is enclosed in { }. So, the value “12” is the value of block and the assignment expression value is Unit which is actually a void type in Java.
Infinite Sequences
Scala’s lists are sequences. Also, these lists are strict sequences which means that the list elements are constructed upfront. But there are non-strict sequences also in which elements are constructed as per the requirement. A list is created by connected the cons cells.
There are 2 such cases :
-
12
::Nil
Here, the con cell has a value and empty tail list. And the list here as only one element.
List[Int] = List(12)
-
12
:
22
: Nil
Here, the cons cell have a value and another list as a tail.
List[Int] = List(22)
The :: symbol is the cons (construct) operator. We invoke the cons operator and Nil is a list. This is how the list grows.
There are 3 ways to create such a list :
- Code 1 :
val geek =
6
::
23
::
45
::Nil
print(geek)
Output :
List(6, 23, 45)
- Code 2 :
val geek = (
6
::(
23
::(
45
::Nil)))
print(geek)
Output :
List(6, 23, 45)
- Code 3 :
val geek = (((Nil.::(
45
)).::(
23
)).::(
6
))
print(geek)
Output :
List(6, 23, 45)
Example :
// Scala program to merge lists // Creating object object GFG { // Main method def main(args : Array[String]) { var a = 5 def fun() = { a + = 1 ; a } lazy val geek = Stream.continually( fun() ) (geek take 10 ) foreach { x => println(x) } } } |
Output :
6 7 8 9 10 11 12 13 14 15
The fun() method is converted to a function. An infinite stream is created by Stream.continually() method. It takes the function and whenever each element is accessed, fun() function is called only at that time to compute that element. This execution of the function on demand is known as Thunk and once it is computed, it goes to the cache for further use which is termed as memoization.