Подтвердить что ты не робот

Когда scala для-понимания ленивы?

В Python я могу сделать что-то вроде этого:

lazy = ((i,j) for i in range(0,10000) for j in range(0,10000))
sum((1 for i in lazy))

Это займет некоторое время, но использование памяти будет постоянным.

Такая же конструкция в scala:

(for(i<-0 to 10000; j<-i+1 to 10000) yield (i,j)).count((a:(Int,Int)) => true)

Через некоторое время я получаю java.lang.OutOfMemoryError, хотя его следует оценивать лениво.

4b9b3361

Ответ 1

Ничто изначально не лениво относится к Scala для понимания; это синтаксический сахар *, который не изменит того факта, что комбинация ваших двух диапазонов будет очень интересной.

Если вы работаете с ленивыми view ваших диапазонов, результат понимания также будет ленивым:

scala> for(i<-(0 to 10000).view; j<-(i+1 to 10000).view) yield (i,j)
res0: scala.collection.SeqView[(Int, Int),Seq[_]] = SeqViewN(...)

scala> res0.count((a: (Int, Int)) => true)
res1: Int = 50005000

Лень здесь не имеет ничего общего с понятием, но потому что, когда flatMap или map (см. ниже) вызывается в контейнере какого-либо типа, вы возвращаете результат в контейнер того же типа. Таким образом, осознание просто сохранит лень (или отсутствие) того, что вы вложили.


* для чего-то вроде:

(0 to 10000).flatMap(i => (i+1 to 10000).map(j => (i, j)))

Ответ 2

Лень приходит не из понимания, а из самой коллекции. Вы должны изучить строгие характеристики коллекции.

Но для ленивых:-) здесь резюме: Iterator и Stream являются нестрогими, так как выбраны методы view любой коллекции. Итак, если вы хотите лень, обязательно сначала .iterator, .view или .toStream свою коллекцию.