简体   繁体   中英

Lazy for comprehension evaluation in scala

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM