2012-05-04 9 views
6

मैं वर्तमान में "प्रोग्रामिंग इन स्कैला" पुस्तक के माध्यम से काम करके स्कैला सीख रहा हूं। अब तक, वहाँ सब कुछ है कि (एक जावा प्रोग्रामर के नजरिए से) अजीब लग रहा है के लिए अच्छा स्पष्टीकरण किया गया है, लेकिन यह एक एक स्ट्रीम का उपयोग कर फाइबोनैचि अनुक्रम उत्पन्न करने के लिए उदाहरण छोड़ देता है मुझे एक तरह से हैरान:स्ट्रीम-विपक्ष # :: स्कैला में अनुवाद कैसे किया जाता है?

def fibFrom(a: Int, b: Int): Stream[Int] = 
    a #:: fibFrom(b, a + b) 

निर्माण कैसे है स्ट्रीम की? बेशक #:: ऑपरेटर किसी भी तरह जिम्मेदार है। मैं समझता हूं कि चूंकि यह : में समाप्त होता है, यह सही-सहयोगी है, लेकिन यह स्ट्रीम के निर्माण की व्याख्या नहीं करता है। मुझे लगता है कि यह किसी भी तरह से एक कन्स्ट्रक्टर में स्पष्ट रूप से अनुवादित है लेकिन मुझे नहीं पता कि क्यों और कैसे बिल्कुल।

मैं पहले से ही Predef.scala और LowPriorityImplicits.scala में जवाब के लिए देखा है, लेकिन कोई किस्मत अब तक।

क्या कोई मुझे प्रबुद्ध कर सकता है?

उत्तर

8

यह सही साहचर्य है, इसलिए यह सही तर्क पर एक तरीके के रूप में काम करता है:

fibFrom(b, a + b).#::(a) 

कम से कम है कि यह वाक्य रचना करने की कोशिश करता क्या है। Stream[Int] में ऐसी कोई विधि नहीं है। सौभाग्य से, object Stream कुछ वर्ग ConsWrapper पर निहित है जिसमें इस विधि (code) है।

तो, आप अंतर्निहित संकल्प के बाद क्या मिलता है यह है:

immutable.this.Stream.consWrapper(fibFrom(b, a + b)).#::(a) 
+0

धन्यवाद, यही वह है। मैं भूल गया कि अंतर्निहित रूपांतरण को कक्षा के साथी वस्तु में भी परिभाषित किया जा सकता है जिसे परिवर्तित किया जाना चाहिए। – rolve

+5

स्कालाडोक शायद उन हार्ड-कोड किए गए साथी implicits को स्वचालित रूप से शामिल करना चाहिए। – Debilski

+2

शायद स्कैला के लिए नए लोगों को इंगित करें कि यह _just_ नहीं है कि यह सही-सहयोगी है। यह भी है कि ConsWrapper '# ::' को लागू करता है [कॉल-बाय-नाम] (https://github.com/scala/scala/blob/v2.10.3/src/library/scala/collection/immutable/Stream। स्केला # L1042)। अर्थात् '⇒'' ConsWrapper (tl: ⇒ stream [ए]) 'में अनुवाद है ताकि अनुवाद' immutable.this.Stream.consWrapper (fibFrom (b, a + b)) में हो। #: :(ए) 'साधन 'fibFrom (बी, ए + बी)' पहुंचने पर कभी भी कॉल किया जाएगा। – nicerobot

2

किसी धारा के एक सूची के समान है। यह केवल उसके सिर और बाकी धारा जानता है: स्ट्रीम (सिर: टी, पूंछ: स्ट्रीम [टी])। अंतर यह है कि एक स्ट्रीम का आलसी मूल्यांकन किया जाता है। विधि के नाम के अंत में ':' कहता है कि विधि सही सहयोगी है। तो अभिव्यक्ति एक # :: fibFrom (बी, ए + बी) का अनुवाद (कंपाइलर द्वारा) fibFrom (बी, ए + बी) में किया जाता है। #: :(ए)।

+0

धन्यवाद, यही मैंने पाया है, लेकिन यह व्याख्या नहीं करता है कि स्ट्रीम ऑब्जेक्ट कैसे बनाया गया है। अगर स्ट्रीम में कोई तरीका था '# ::', तो यह मुझे लगता है कि एक अनंत रिकर्सन का कारण होगा। – rolve

+0

# :: सूची में :: जैसा ही है। और हाँ यह एक अनंत रिकर्सन है। आप बस अपने इच्छित तत्वों की संख्या लेते हैं। यही वह था जिसे मैं व्यक्त करना चाहता था कि यह आलसी मूल्यांकन किया गया है। इसका मतलब यह है कि कंप्यूटिंग की आवश्यकता होने पर इसकी गणना की जाएगी। –

+0

यह बिल्कुल वही नहीं है, नहीं। यदि यह वही था, तो आपके पास अनंत असंतोष होगा। इसके बजाए, '# :: '(कक्षा' ConsWrapper' में परिभाषित, स्ट्रीम नहीं!) में एक उप-नाम पैरामीटर है जिसका मूल्यांकन आलसी रूप से किया जाता है। – rolve

संबंधित मुद्दे