2015-07-05 4 views
7

lazy क्यों उपयोग किया जाता है?स्विफ्ट में आलस्य

extension SequenceType { 
    func mapSome<U>(transform: Generator.Element -> U?) -> [U] { 
     var result: [U] = [] 
     for case let x? in lazy(self).map(transform) { 
      result.append(x) 
     } 
     return result 
    } 
} 

इस विस्तार के एक परिवर्तन समारोह है कि एक वैकल्पिक रिटर्न लेता है, और केवल उन मूल्यों की एक सरणी है कि शून्य

में तब्दील नहीं कर रहे थे क्यों नहीं बस self.map(transform) का उपयोग देता है? आलस्य यहाँ जरूरी है?

+0

वैसे, 'flatMap (परिवर्तन: जेनरेटर.एमेंटमेंट -> यू?) -> [यू] 'अब स्विफ्ट 2 मानक लाइब्रेरी में उपलब्ध है :) – jtbandes

उत्तर

11

यह एक मध्यवर्ती सरणी के निर्माण से बचाता है।

self.map(transform) 

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

lazy(self).map(transform) 

एक अनुक्रम तब्दील तत्वों की है, जो है तो से अधिक दोहराया गैर शून्य तत्व प्राप्त करने के लिए है। परिवर्तनित तत्व गणना के दौरान गणना की जाती है। (आलसी क्रम पर next() को प्रत्येक कॉल मूल अनुक्रम के अगले तत्व बदलने से एक तत्व पैदा करता है।)

दोनों ही तरीकों से काम करते हैं। आलसी विधि शायद बड़े अनुक्रमों के लिए बेहतर प्रदर्शन करेगी, लेकिन यह कई कारकों (आकार सरणी के आधार पर निर्भर हो सकती है, चाहे तत्व मान या संदर्भ प्रकार हों, सरणी तत्वों की प्रतिलिपि बनाना कितना महंगा है)। छोटे सरणी के लिए अतिरिक्त ओवरहेड के कारण आलसी विधि शायद धीमी हो जाएगी। एक ठोस आवेदन में, उपकरण के साथ प्रोफाइलिंग यह तय करने में सहायता करेगा कि किस विधि का उपयोग करना है।

+1

मेरा (स्वीकार्य रूप से अनौपचारिक) प्रदर्शन परीक्षणों से पता चलता है कि आलसी और गैर आलसी छोटे सरणी के लिए समान रूप से प्रदर्शन करते हैं, लेकिन वह आलसी बड़े पैमाने पर एक मामूली बढ़त देता है वाले, इसलिए इसमें शामिल है (विशेष रूप से इस तरह के लाइब्रेरी फ़ंक्शन में)। दिलचस्प बात यह है कि 'flatMap', जो 2.0 के रूप में अब यह तर्क करता है, दोनों से भी बदतर है। –

+0

@AirspeedVelocity: यह दिलचस्प है, प्रतिक्रिया के लिए धन्यवाद। –

+0

दिलचस्प बात यह है कि मुझे विपरीत परिणाम मिल गया है !? नीचे मेरा जवाब देखें। – Qbyte

5

के रूप में मार्टिन आर lazy() एक मध्यवर्ती सरणी के निर्माण से बचा जाता है का उल्लेख किया। हालांकि अगर मैं विभिन्न आकारों के सरणी पर फ़ंक्शन के निष्पादन समय की तुलना करता हूं तो आपको लगता है कि lazy() "केवल" 10% तेज है।

दिलचस्प बात यह है कि आप पाते हैं कि lazy() 200 से कम तत्वों के साथ सरणी के लिए 2 गुना तेज है और अधिक तत्वों के साथ रूपांतरण के बिना फ़ंक्शन के रूप में लगभग उतना तेज़ होता है (10% तेज)।

((संकलित) स्रोत फ़ाइलों के रूप में एक खेल का मैदान में Xcode 6.4 और Xcode 7 के साथ परीक्षण किया गया वैश्विक कार्य करता है और प्रोटोकॉल एक्सटेंशन के साथ)

तो lazy() बल्कि Sequences के लिए इस्तेमाल किया जाएगा, जहाँ आप अगर यह परिमित है पता नहीं है । फिर, छोरों के लिए संभावना break या return साथ किया जाता है:

for element in lazy(sequence).map{ ... } { 
    if element == 1000 { 
     break 
    } 
    // use element 
} 

यदि आप एक अनंत Sequence (जैसे 1,2,3 ...) निष्पादन नक्शे पर फोन भी अनंत होगा। lazy() के साथ परिवर्तन और निष्पादन "देरी" हो जाता है इस प्रकार आप अंतिम तत्व से पहले लूप से बाहर निकलने पर "बड़े" और अनंत अनुक्रमों को अधिक कुशलता से संभाल सकते हैं।

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