2012-09-13 11 views
14

मैं इस धारणा के तहत था कि आलसी seqs हमेशा चुस्त थे।क्लोजर में, आलसी seqs हमेशा चुस्त हैं?

=> (take 1 (map #(do (print \.) %) (range))) 
(................................0) 

के रूप में की उम्मीद 32 डॉट्स मुद्रित कर रहे हैं क्योंकि आलसी seq range द्वारा लौटाए गए 32 तत्व टुकड़ों में chunked है। हालांकि, जब range के बजाय मैं अपने खुद के समारोह get-rss-feeds के साथ इस कोशिश, आलसी seq नहीं रह गया है chunked है:

=> (take 1 (map #(do (print \.) %) (get-rss-feeds r))) 
(."http://wholehealthsource.blogspot.com/feeds/posts/default") 

केवल एक डॉट छपा है, इसलिए मुझे लगता है कि आलसी-सेक get-rss-feeds द्वारा दिया chunked नहीं है। दरअसल:

(defn get-rss-feeds 
    "returns a lazy seq of urls of all feeds; takes an html-resource from the enlive library" 
    [hr] 
    (map #(:href (:attrs %)) 
     (filter #(rss-feed? (:type (:attrs %))) (html/select hr [:link]))) 

तो ऐसा लगता है कि chunkiness कैसे आलसी seq उत्पादन किया जाता है पर निर्भर करता है:

=> (chunked-seq? (seq (range))) 
true 

=> (chunked-seq? (seq (get-rss-feeds r))) 
false 

यहाँ get-rss-feeds के लिए स्रोत है। मैंने range समारोह के स्रोत पर देखा और इसके संकेतों को "चंकी" तरीके से लागू किया जा रहा है। तो मैं थोड़ा उलझन में हूं कि यह कैसे काम करता है। क्या कोई स्पष्टीकरण दे सकता है?


यहां मुझे क्यों पता होना चाहिए।

मैं निम्नलिखित कोड है: (get-rss-entry (get-rss-feeds h-res) url)

get-rss-feeds करने के लिए कॉल फ़ीड है कि मैं जांच करने के लिए की जरूरत का यूआरएल की एक आलसी अनुक्रम देता है।

get-rss-entry पर कॉल एक विशेष प्रविष्टि की तलाश करता है (जिसका: लिंक फ़ील्ड गेट-आरएसएस-एंट्री के दूसरे तर्क से मेल खाता है)। यह get-rss-feeds द्वारा आलसी अनुक्रम की जांच करता है। प्रत्येक आइटम का मूल्यांकन करने के लिए एक नई आरएसएस फ़ीड लाने के लिए नेटवर्क पर एक http अनुरोध की आवश्यकता होती है। Http अनुरोधों की संख्या को कम करने के लिए अनुक्रम की जांच करना महत्वपूर्ण है और एक मैच होने पर ही रोकें।

(defn get-rss-entry 
    [feeds url] 
    (ffirst (drop-while empty? (map #(entry-with-url % url) feeds)))) 

entry-with-url मैचों की एक आलसी अनुक्रम या एक खाली अनुक्रम रिटर्न अगर वहाँ कोई मुकाबला नहीं है:

यहाँ कोड है।

मैंने इसका परीक्षण किया और ऐसा लगता है कि यह सही ढंग से काम करता है (एक समय में एक फ़ीड यूआरएल का मूल्यांकन)। लेकिन मुझे चिंता है कि कहीं, किसी भी तरह से यह एक "चंकी" तरीके से व्यवहार करना शुरू कर देगा और यह एक समय में 32 फीड का मूल्यांकन शुरू कर देगा। मुझे पता है कि avoid chunky behavior as discussed here का कोई तरीका है, लेकिन ऐसा लगता है कि इस मामले में भी इसकी आवश्यकता नहीं है।

क्या मैं आलसी सीक गैर-idiomatically उपयोग कर रहा हूँ? लूप/रिकर एक बेहतर विकल्प होगा?

+0

ऐसा लगता है कि एक दृश्य केवल कि "chunked" आप 'clojure.core' में विभिन्न हिस्सा कार्यों का उपयोग और/या अपने अनुक्रम को लागू करता है, तो' IChunk' और 'IChunkedSeq' इंटरफेस। वर्तमान में (1.4.0 में), ये अनियंत्रित हैं। – noahlz

+0

क्लोजर का आप किस संस्करण का उपयोग कर रहे हैं? –

+0

मैं क्लोजर v1.4 –

उत्तर

3

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

+2

का उपयोग कर रहा हूं क्या आप इस पर नमूना कोड के एक स्केच के साथ विस्तार कर सकते हैं? क्या आप परमाणुओं के बजाय एजेंटों का मतलब है? – noahlz

+0

क्या आप यहां परमाणु के बजाय एजेंट का मतलब है? क्योंकि स्वैप के लिए प्रदान किए गए कार्यों! – noisesmith

+0

एस/परमाणु/एजेंट/जी इसके बारे में खेद है। मेरी उंगलियां मेरे मस्तिष्क को धोखा देती हैं और गलत कुंजी दबाती हैं ... तय की जाती है। –

5

आलसी seqs हमेशा नहीं है - यह इस बात पर निर्भर करता है कि वे कैसे उत्पादित होते हैं।

उदाहरण के लिए, आलसी seq इस समारोह द्वारा उत्पादित chunked नहीं है:

(defn integers-from [n] 
    (lazy-seq (cons n (do (print \.) (integers-from (inc n)))))) 

(take 3 (integers-from 3)) 
=> (..3 .4 5) 

लेकिन कई अन्य clojure बिल्ट-इन कार्य प्रदर्शन कारणों से chunked seqs (जैसे range)

+1

यह जोड़ना बहुत महत्वपूर्ण है कि 'मानचित्र' और 'फ़िल्टर' दोनों चंकित seqs उत्पन्न कर सकते हैं। मिश्रण दुष्प्रभाव और आलस्य सूक्ष्म बग के लिए एक नुस्खा है। ट्रांसड्यूसर यहां मदद करते हैं। –

11

आप कर रहे हैं उत्पादन करना चिंतित होने का अधिकार वास्तव में entry-with-url को कड़ाई से जरूरी से अधिक कॉल करेगा यदि feeds पैरामीटर एक संग्रह है जो खंडित seqs देता है। उदाहरण के लिए यदि feeds एक वेक्टर है, map एक समय में पूरे हिस्सों पर काम करेगा।

यह समस्या समारोह seq1 अध्याय 12 में परिभाषित के साथ, Fogus 'Clojure की जोय में सीधे संबोधित किया जाता है:

(defn seq1 [s] 
    (lazy-seq 
    (when-let [[x] (seq s)] 
     (cons x (seq1 (rest s)))))) 

आप सही यह सही है जहाँ आप जानते हैं कि आप सबसे आलस्य संभव चाहते इस्तेमाल कर सकते हैं, इससे पहले कि आप फोन entry-with-url:

 
(defn get-rss-entry 
    [feeds url] 
    (ffirst (drop-while empty? (map #(entry-with-url % url) (seq1 feeds))))) 
+0

बहुत बहुत धन्यवाद। बीटीडब्ल्यू ने अभी पुस्तक समाप्त की और यह मेरा क्लोजर गेम अगले स्तर पर ले गया। अद्यतन संस्करण के लिए इंतजार नहीं कर सकता। –

+0

यह इंगित करने लायक है कि 'seq1' को यह अनचाहे कॉल _at source_ किया जाना है। यदि आप एक चंकित अनुक्रम पर 'मानचित्र' से आलसी अनुक्रम प्राप्त कर रहे हैं, उदाहरण के लिए, आप भाग्य से बाहर हैं - 'नक्शा' आगे बढ़ने जा रहा है इससे कोई फर्क नहीं पड़ता कि आप क्या करते हैं। – Thom

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