I'm new to scala and most functional languages and I'm currently trying to factor a number. i've written the code:
lazy val factors = for(int <- 2 until math.ceil(math.sqrt(number)).toInt if number%int == 0) yield int
I was wondering If I declared the scala val as lazy will it not evaluate the entire for comprehension when I call factors.head
?
Your factors
variable is lazy; the for
comprehension isn't. When you access factors
the first time, your for
comprehension will be fully evaluated.
In Scala, for
comprehension is merely a sugar for flatMap
, map
, and withFilter
method calls. So if your backing data structure is strict (such as Range
- which is what you are using), your for
comprehension will also be strict. If the data structure is lazy (such as Stream
), so will be for
comprehension.
Observe the difference:
scala> val number = 50
number: Int = 50
scala> lazy val factors = for(int <- 2 until math.ceil(math.sqrt(number)).toInt if number%int == 0) yield int
factors: scala.collection.immutable.IndexedSeq[Int] = <lazy>
scala> factors.head
res5: Int = 2
scala> factors
res6: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 5)
scala> lazy val factors = for(int <- Stream.range(2, math.ceil(math.sqrt(number)).toInt - 1) if number%int == 0) yield int
factors: scala.collection.immutable.Stream[Int] = <lazy>
scala> factors.head
res7: Int = 2
scala> factors
res8: scala.collection.immutable.Stream[Int] = Stream(2, ?)
No. It is a completely different thing: lazy
means that the value is computed the first time you access to it. If you want lazy computation for collections, you should use Stream
or use a view. A Stream
can be built from a collection using view
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With