2011-08-09 16 views
12

, böyle bir şey yapabilirsiniz:Scala'nın kavrayışları ne zaman tembel? Python

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

biraz zaman alacak, ama hafıza kullanımı sabittir. Scala içinde

aynı yapı:

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

Bir süre sonra, bunun lazily değerlendirilmelidir rağmen bir java.lang.OutOfMemoryError olsun.

cevap

22

Scala'nın anlaşılırlığı hakkında hiçbir şey temkinli değildir; Bu sözdizimsel şeker * ki bu iki aralığınızın kombinasyonunun istekli olacağını değiştirmeyecektir. Eğer aralıklarının tembel view s ile çalışıyorsanız

, anlama sonucu tembel olacaktır:

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 

burada tembellik ile ilgisi olduğu için-anlama, fakat ne zaman flatMap veya map (aşağıya bakın) bir tür kapsayıcıda çağrılır, sonuçta aynı kapsayıcıda bir sonuç alırsınız. Yani, for-anlama sadece ne olursa olsun size koymak (veya eksikliği) tembelliğe koruyacak


* gibi bir şey için:.

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

"Bir şey gibi", ancak bu ikinci ifade, 50005000 değil 100020001 öğeye dönüyor gibi görünüyor. Viski tango foxtrot? – Malvolio

+0

@Malvolio Fark ettiğin için teşekkürler! j', 1'den 10000'e, 1'den 10000'e kadar olmalıdır. Şimdi sabit. –

+0

D'oh. Çözümü fark etmeliydim, sadece sorun değil. Argümanları göz ardı ederek harita fonksiyonlarına bakıyordum .. – Malvolio

11

Tembellik için-kavrama değil, gelir, ama koleksiyonun kendisinden. Koleksiyonun katılık özelliklerine bakmalısınız.

Ancak, tembel :-) için, burada bir özet: Iterator ve Stream, herhangi bir koleksiyonun view seçili yöntemleri olarak katı değildir. Yani, tembellik istiyorsanız, ilk önce koleksiyonunuzu .iterator, .view veya .toStream'dan emin olun.

İlgili konular