स्काला: स्कैला संग्रह में ट्रैवर्सेबल और Iterable लक्षण के बीच अंतर क्या है?


98

मैंने इस प्रश्न को देखा है, लेकिन अभी भी Iterable और Traversable लक्षण के बीच अंतर को नहीं समझता। क्या कोई समझा सकता है?


2
स्काला २.१३Traversable में अधिक नहीं है (इसे २.१४ तक अभी भी एक अलग उर्फ ​​के रूप में रखा गया है )Iterable
जेवियर गुइहोट

जवाबों:


121

इसे सीधे शब्दों में कहें तो पुनरावृत्तियां राज्य रखती हैं, ट्रैवर्सबेल नहीं।

एक Traversableसार विधि है foreach:। जब आप कॉल करते हैं foreach, तो संग्रह पारित फ़ंक्शन को सभी तत्वों को खिलाएगा, एक के बाद एक।

दूसरी ओर, एक Iterableसार पद्धति है iterator, जो एक रिटर्न देता है Iterator। आप कॉल कर सकते हैं nextएक पर Iteratorअपने चयन के समय में अगले तत्व प्राप्त करने के लिए। जब तक आप ऐसा नहीं करते, तब तक इस बात का ध्यान रखना होगा कि यह संग्रह में कहाँ था, और आगे क्या है।


4
लेकिन Iterableविस्तार करता है Traversable, इसलिए मुझे लगता है कि आप का मतलब है Traversableकि Iterableएस नहीं हैं ।
रॉबिन ग्रीन

4
@ रॉबिनग्रीन मेरा मतलब है कि Traversableइंटरफ़ेस का अनुपालन करने के लिए राज्य को रखने की आवश्यकता नहीं होती है, जबकि Iteratorइंटरफ़ेस का अनुपालन होता है।
डैनियल सी। सोबरल

10
Traversables जो Iterableकिसी पुनरावृत्ति स्थिति को नहीं रखते हैं। यह Iteratorबनाया गया है और Iterableराज्य द्वारा लौटाया गया है ।
ग्राहम ली

1
यह ध्यान देने योग्य है कि 2.13 विशेषता के रूप में ट्रैवर्सेबल को हटा दिया गया है। स्टीफन ज़ाइगर के उद्धरण के लिए, "ट्रैवर्सेबल अमूर्तता ने वर्तमान पुस्तकालय में अपना वजन नहीं बढ़ाया है और संभवतः नए डिजाइन में पुनरुत्थान नहीं होगा। हम जो कुछ करना चाहते हैं वह Iterable के साथ व्यक्त किया जा सकता है।"
इगोर उर्र्समैन

226

इसे उड़ाने और चूसने के बीच के अंतर के रूप में सोचें।

जब आपके पास एक Traversableएस foreach, या इसके व्युत्पन्न तरीके होते हैं, तो यह एक बार में आपके मूल्यों को अपने फ़ंक्शन में उड़ा देगा - इसलिए इसका नियंत्रण पर नियंत्रण है।

हालांकि Iteratorएक लौटे के साथ Iterable, आप इसके मूल्यों को चूसते हैं, नियंत्रित करते हैं कि अगले एक को कब स्थानांतरित किया जाए।


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

2
मेरे अगले साक्षात्कार में पूछे जाने पर इसे कभी न
भूलें

23

tl; dr Iterables हैं Traversablesजो स्टेटफुल प्रोड्यूस कर सकते हैंIterators


सबसे पहले, पता है कि Iterableकी उप-सीमा है Traversable

दूसरा,

  • Traversableforeachविधि को लागू करने की आवश्यकता होती है , जो हर चीज द्वारा उपयोग की जाती है।

  • Iterableiteratorविधि को लागू करने की आवश्यकता होती है , जो हर चीज द्वारा उपयोग की जाती है।

उदाहरण के लिए, एक संतोषजनक तत्व पाए जाने findके बाद Traversableउपयोग के लिए का उपयोग foreach(एक समझ के लिए) और BreakControlइसके अपवाद को रोक देता है।

trait TravserableLike {
  def find(p: A => Boolean): Option[A] = {
    var result: Option[A] = None
    breakable {
      for (x <- this)
        if (p(x)) { result = Some(x); break }
    }
    result
  }
}

इसके विपरीत, Iterableघटाव इस कार्यान्वयन को ओवरराइड करता है और कॉल findकरता है Iterator, जो कि तत्व मिलने पर बस पुनरावृति को रोकता है:

trait Iterable {
  override /*TraversableLike*/ def find(p: A => Boolean): Option[A] =
    iterator.find(p)
}

trait Iterator {
  def find(p: A => Boolean): Option[A] = {
    var res: Option[A] = None
      while (res.isEmpty && hasNext) {
        val e = next()
        if (p(e)) res = Some(e)
      }
    res
  }
}

यह अच्छा होगा Traversableकि पुनरावृत्ति के लिए अपवाद न फेंके , लेकिन यह केवल आंशिक रूप से पुनरावृति का एकमात्र तरीका है जब बस का उपयोग किया जाए foreach

एक दृष्टिकोण से, Iterableअधिक मांग / शक्तिशाली विशेषता है, जैसा कि आप आसानी से foreachउपयोग करके लागू कर सकते हैं iterator, लेकिन आप वास्तव में iteratorउपयोग करके लागू नहीं कर सकते हैं foreach


सारांश में, Iterableएक स्टेटफुल के माध्यम से इसे रोकने, फिर से शुरू करने या पुनरावृत्ति को रोकने का एक तरीका प्रदान करता है Iterator। इसके साथ Traversable, यह सब या कुछ भी नहीं है (प्रवाह नियंत्रण के लिए अपवाद हैं)।

अधिकांश समय यह मायने नहीं रखता है, और आप अधिक सामान्य इंटरफ़ेस चाहते हैं। लेकिन अगर आपको कभी भी पुनरावृत्ति पर अधिक अनुकूलित नियंत्रण की आवश्यकता है, तो आपको एक की आवश्यकता होगी Iterator, जिसे आप एक से पुनः प्राप्त कर सकते हैं Iterable


1

डैनियल का जवाब अच्छा लगता है। मुझे देखने दीजिए कि क्या मैं इसे अपने शब्दों में रख सकता हूं।

तो एक Iterable आपको एक पुनरावृत्ति दे सकता है, जिससे आप तत्वों को एक समय में (अगले () का उपयोग करके) पार कर सकते हैं, और रुकें और अपनी इच्छानुसार जाएँ। ऐसा करने के लिए कि पुनरावृत्त को तत्व की स्थिति में एक आंतरिक "पॉइंटर" रखने की आवश्यकता है। लेकिन एक ट्रैवर्सेबल आपको बिना रोक-टोक के एक बार में सभी तत्वों को ट्रेस करने के लिए विधि, फ़ॉरचेक देता है।

रेंज (1, 10) जैसी कुछ चीज़ों को ट्रैवर्सेबल के रूप में केवल 2 पूर्णांक होने की आवश्यकता है। लेकिन रेंज (1, 10) Iterable के रूप में आपको एक पुनरावृत्ति देता है जिसे राज्य के लिए 3 पूर्णांक का उपयोग करने की आवश्यकता होती है, जिनमें से एक सूचकांक है।

यह मानते हुए कि ट्रैवर्सेबल भी फोल्डेफ्ट, फोल्डराइट प्रदान करता है, इसके फोरचेक को एक ज्ञात और निश्चित क्रम में तत्वों को पीछे हटाना होगा। इसलिए ट्रैवर्सेबल के लिए पुनरावृति लागू करना संभव है। जैसे डिफ इटेरेटर = लिस्ट.इटरेटर

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.