2011-08-09 2 views
12

, 나는 이런 식으로 뭔가를 할 수 있습니다스칼라의 for-comprehensions은 언제 게으른가요? 파이썬에서

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

이 걸릴 것이다, 그러나 메모리 사용은 일정하다. 스칼라에서

같은 구조 :

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

잠시 후, 나는 그것이 게으르게 평가해야에도 불구하고 java.lang.OutOfMemoryError를 얻을.

답변

22

스칼라의 이해에 본질적으로 게으른 것은 없습니다. 그것은 당신의 두 범위의 결합이 열망 할 것이라는 사실을 바꾸지 않을 통 신당입니다. 당신이 당신의 범위 게으른 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))) 
+0

"비슷한"하지만 후자의 표현은 50005000이 아닌 100020001 개 요소를 반환하는 것으로 보입니다. Whisky tango foxtrot? – Malvolio

+0

@Malvolio는주의를 기울여 주셔서 감사합니다! 'j '는'1에서 10000 '이 아니라'i + 1에서 10000 '사이 여야합니다. 이제 해결되었습니다. –

+0

D' oh. 나는 단지 문제 만이 아니라 그 해결책을 알아 차렸을 것입니다. 인수를 무시하고지도 함수를 쳐다보고 있었다. – Malvolio

11

게으름이를위한 이해에서하지 온다, 컬렉션 자체에서 가져온 것입니다. 컬렉션의 엄격 성 특성을 조사해야합니다.

그러나 게으른 사람들을 위해 : IteratorStream은 임의의 컬렉션 중 view의 선택된 메소드와 마찬가지로 엄격하지 않습니다. 따라서 게으름을 원하면 .iterator, .view 또는 .toStream 컬렉션을 먼저 읽으십시오.