2012-09-27 12 views
6

उत्पादन नहीं करता है क्यों है यह है कि,स्काला नक्शा दुष्प्रभाव

scala> List(1,2,3,4).iterator.map((x: Int) => println(x)) 

प्रिंट आउट नहीं करता

1 
2 
3 
4 

जबकि

List(1,2,3,4).map((x: Int) => println(x)) 
List(1,2,3,4).foreach((x: Int) => println(x)) 
List(1,2,3,4).iterator.foreach((x: Int) => println(x)) 

सब करते हैं?

दूसरे शब्दों में, यह क्यों है कि एक पुनरावर्तक पर एक मानचित्र जो टी को यूनिट टाइप करता है और साइड इफेक्ट्स उन दुष्प्रभावों को दिखाने में असमर्थ हैं?

संपादित करें:

भी क्यों lazyMap के निम्नलिखित मंगलाचरण वास्तव में अगर इटरेटर आलसी है समाप्त करने के लिए शुरू से ही नई इटरेटर (पूरा नया इटरेटर प्रदान) की गणना करता है? पुनरावर्तक पर

def lazyMap[T, U](coll: Iterable[T], f: T => U) = new Iterable[U] { 
    def iterator = coll.iterator map f 
} 

scala> lazyMap(List(1,2,3,4), (x: Int) => x + 1) 
res4: java.lang.Object with Iterable[Int] = (2, 3, 4, 5) 
+0

वैसे, आप Iterable का गलत विस्तार कर रहे हैं (Iterable को बढ़ाने वाले सभी वर्गों को 'newBuilder' विधि प्रदान करना चाहिए) –

उत्तर

7

कारण मानचित्र आलसी है और आप कुछ कठोरता की जरूरत है:

scala> List(1,2,3,4).iterator.map((x: Int) => println(x)) 
res0: Iterator[Unit] = non-empty iterator 

// nothing actually happened yet, just remember to do this printing things 

scala> res0.toList 
1 
2 
3 
4 
res1: List[Unit] = List((),(),(),()) 

आप foreach पुनरावर्तक पर यह काफी स्पष्ट है कि आप साइड इफेक्ट कर रहे है कर रहे हैं, तो lazyness अवांछित हो जाएगा। मैं मानचित्र के बारे में ऐसा नहीं कहूंगा।

युपीडी

आपके संपादन के लिए के रूप में: इस तरह के व्यवहार के लिए कारण, वहाँ बयान परिणाम के लिए toString की अंतर्निहित कॉल जो बारी में इटरेटर stricts है कि - अपने दम पर इस कोड का प्रयास करें:

scala> { lazyMap(List(1,2,3,4), {(x: Int) => println(x); x + 1}); 1 } 

और आप देखेंगे कि समारोह f

6

एक इटरेटर बिंदु कहा जाता कभी नहीं है आलस्य है। दूसरे शब्दों में, जब आप एक इटरेटर बनाते हैं, तब तक यह कुछ भी मूल्यांकन नहीं करेगा जब तक आप डेटा को पढ़ने के लिए नहीं जाते। यहां ऐसा लगता है:

scala> val itr = List(1,2,3).iterator 
itr: Iterator[Int] = non-empty iterator 

ठीक है, अब हमारे पास एक इटरेटर है। लेकिन यह वास्तव में अभी तक सूची में नहीं देखा है।

scala> val mappedItr = itr.map((x: Int) => println(x)) 
mappedItr: Iterator[Unit] = non-empty iterator 

अब हमारे पास एक नया इटरेटर है। यह एक होगा, जब डेटा का उपयोग किया जाता है, मैप किए गए फ़ंक्शन को लागू करें। लेकिन हम अभी भी वास्तव में मूल सूची को नहीं देखा है।

scala> mappedItr.next 
1 

यह पहली बार हम डेटा को एक्सेस किया है है, इसलिए यह पहली बार है कि इटरेटर सूची में देखा गया है। हमने next कहा, इसलिए हमें पहला तत्व मिला। चूंकि हमारे इटेटर के पास map कतारबद्ध है, इसलिए जब हम उस तत्व तक पहुंचते हैं तो यह मैप किए गए फ़ंक्शन को लागू करता है। इसलिए हम next आइटम पर लागू फ़ंक्शन का परिणाम देखते हैं।

हम अगले तत्व प्राप्त करने के लिए इसे फिर से कर सकते हैं:

scala> mappedItr.next 
2 

और, फिर से, यह समारोह का मूल्यांकन करता है केवल जब यह आदेश हमें अंतिम परिणाम देने के लिए, की जरूरत है।

+0

कृपया संपादित करें – platypus