ध्यान दें कि लेखक यहां स्केल मानक लाइब्रेरी में किसी भी फ़ोल्ड राइट परिभाषा का जिक्र नहीं कर रहे हैं, जैसे सूची में परिभाषित एक। वे धारा 3.4 में ऊपर दिए गए फ़ोल्ड राइट की परिभाषा का जिक्र कर रहे हैं।
स्कैला मानक लाइब्रेरी सूची को उलटकर फ़ोल्ड लाइफ के संदर्भ में फ़ोल्ड राइट को परिभाषित करता है (जिसे निरंतर स्टैक स्पेस में किया जा सकता है) फिर पास किए गए फ़ंक्शन के तर्कों के साथ फ़ोल्डलिफ्ट को कॉल करना। इस सूची के लिए काम करता है, लेकिन, एक संरचना जो सुरक्षित रूप से वापस नहीं लिया जा सकता है के लिए काम नहीं करेगा उदाहरण के लिए:
scala> Stream.continually(false)
res0: scala.collection.immutable.Stream[Boolean] = Stream(false, ?)
scala> res0.reverse
java.lang.OutOfMemoryError: GC overhead limit exceeded
अब देता है क्या इस ऑपरेशन का परिणाम होना चाहिए के बारे में सोचना:
Stream.continually(false).foldRight(true)(_ && _)
उत्तर गलत होना चाहिए, इससे कोई फर्क नहीं पड़ता कि धारा में कितने झूठे मूल्य हैं या यदि यह अनंत है, तो यदि हम उन्हें संयोजन के साथ जोड़ना चाहते हैं, तो परिणाम गलत होगा। निश्चित रूप से
Haskell कोई समस्या नहीं के साथ इस हो जाता है:
Prelude> foldr (&&) True (repeat False)
False
और उस वजह से दो महत्वपूर्ण बातें की है: हास्केल के foldr धारा पार किए जाने की सही करने के लिए छोड़ दिया है, सही करने के लिए नहीं से छोड़ दिया, और हास्केल द्वारा आलसी है चूक। यहां पहला आइटम, वह फ़ोल्डर वास्तव में बाएं से दाएं की सूची को घुमाता है, जो कुछ लोगों को सही से शुरू करने के रूप में सही गुना के बारे में सोचने वाले लोगों को आश्चर्यचकित या भ्रमित कर सकता है, लेकिन सही गुना की महत्वपूर्ण विशेषता यह नहीं है कि यह किस संरचना से शुरू होता है पर, लेकिन किस दिशा में सहयोगीता है। तो [1,2,3,4], एक सूची और एक सेशन op
नाम के एक बाईं गुना
((1 op 2) op 3) op 4)
है और एक सही गुना
(1 op (2 op (3 op 4)))
है लेकिन मूल्यांकन के आदेश नहीं करना चाहिए देना मामला। तो अध्याय 3 में लेखकों ने यहां क्या किया है, यह आपको एक गुना देना है जो सूची को बाएं से दाएं स्थानांतरित करता है, लेकिन क्योंकि स्कैला डिफ़ॉल्ट रूप से सख्त है, हम अभी भी अनंत झूठी धाराओं को पार करने में सक्षम नहीं होंगे, लेकिन कुछ धैर्य, वे अध्याय 5 में उस पर पहुंच जाएंगे :) मैं आपको एक चुपके की चोटी दूंगा, चलिए फ्लाई राइट के बीच अंतर को देखते हैं क्योंकि इसे मानक पुस्तकालय में परिभाषित किया गया है और इसे स्केलज़ में फोल्डबल टाइपक्लास में परिभाषित किया गया है:
def foldRight[B](z: B)(op: (A, B) => B): B
यहाँ है scalaz के Foldable से परिभाषा:
यहाँ स्केला मानक पुस्तकालय से कार्यान्वयन है
अंतर यह है कि बी एस सभी आलसी हैं, और अब हम हमारे अनंत धारा फिर से गुना करने के लिए मिलता है, जब तक हम एक समारोह है जो अपनी दूसरा पैरामीटर में पर्याप्त रूप से आलसी है देने के रूप में:
scala> Foldable[Stream].foldRight(Stream.continually(false),true)(_ && _)
res0: Boolean = false
हास्केल में 'फ़ोल्डर' पूंछ-रिकर्सिव नहीं है, इसलिए यह अभी भी अतिप्रवाह त्रुटियों को ढेर करने के लिए प्रवण है। हास्केल में क्या अलग है आलसी मूल्यांकन अर्थशास्त्र, जो कभी-कभी 'फोल्डर' को फोल्डिंग ऑपरेटर के दोनों * तर्कों का मूल्यांकन नहीं करने देता है। यहां अधिक जानकारी: http://www.haskell.org/haskellwiki/Stack_overflow –
इसके अलावा, स्कैला की अंतर्निहित 'फ़ोल्ड राइट' विधि स्टैक ओवरफ्लो (अब) के लिए प्रवण नहीं है, क्योंकि यह उल्टा सूची पर 'foldLeft' कहती है, और 'foldLeft' भी पुनरावर्ती नहीं है। https://github.com/scala/scala/blob/v2.11.2/src/library/scala/collection/immutable/List.scala#L396-L397 https://github.com/scala/scala/blob/v2 .11.2/src/library/scala/collection/LinearSeqOptimized.scala # L105-L114 –
पुराने स्कैला के पुराने 'foldRight' के लिए टिकट: https://issues.scala-lang.org/browse/SI-3295 –