2011-08-09 17 views
12

अजगर में, मैं कुछ इस तरह कर सकते हैं:स्कैला के लिए समझदारी कब आलसी है?

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 मिलता है, भले ही यह lazily मूल्यांकन किया जाना चाहिए।

उत्तर

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

"कुछ पसंद है", लेकिन बाद की अभिव्यक्ति 100000001 तत्वों को वापस लौटती है, 50005000 नहीं। व्हिस्की टैंगो फॉक्सट्रॉट? – Malvolio

+0

@ माल्वोलियो ध्यान देने के लिए धन्यवाद! 'j'' i + 1 से 10000' तक होना चाहिए, न कि '1 से 10000'। अब तय –

+0

डी ओह। मुझे केवल समस्या ही नहीं, समाधान देखा जाना चाहिए था। मैं तर्कों को अनदेखा कर, मानचित्र कार्यों पर घूर रहा था .. – Malvolio

11

आलस्य के लिए-समझ से नहीं आता, लेकिन संग्रह से ही। आपको संग्रह की कठोरता विशेषताओं को देखना चाहिए।

लेकिन, आलसी :-) के लिए, यहां सारांश है: Iterator और Stream गैर-सख्त हैं, जैसा कि किसी संग्रह के view के चयनित तरीके हैं। इसलिए, यदि आप आलस्य चाहते हैं, तो .iterator, .view या .toStream अपने संग्रह को पहले सुनिश्चित करें।