2012-11-08 5 views
6

में हेड प्रतिधारण "क्लोजर प्रोग्रामिंग" (पृष्ठ 98) में मुख्य प्रतिधारण के बारे में पैराग्राफ पढ़ना, मुझे पता नहीं लगा कि split-with उदाहरण में क्या होता है। मैंने प्रतिलिपि के साथ प्रयोग करने की कोशिश की है लेकिन यह मुझे और अधिक भ्रमित कर दिया है।क्लोजर

(time (let [r (range 1e7) 
      a (take-while #(< % 12) r) 
      b (drop-while #(< % 12) r)] 
     [(count a) (count b)])) 
"Elapsed time: 1910.401711 msecs" 
[12 9999988] 

(time (let [r (range 1e7) 
      a (take-while #(< % 12) r) 
      b (drop-while #(< % 12) r)] 
     [(count b) (count a)])) 
"Elapsed time: 3580.473787 msecs" 
[9999988 12] 

(time (let [r (range 1e7) 
      a (take-while #(< % 12) r) 
      b (drop-while #(< % 12) r)] 
     [(count b)])) 
"Elapsed time: 3516.70982 msecs" 
[9999988] 

आप पिछले उदाहरण से देख सकते हैं, अगर मैं a गणना नहीं है, समय किसी भी तरह लेने वाली होती है। मुझे लगता है, मैंने यहाँ कुछ याद किया है, लेकिन क्या?

+1

यह प्रश्न http://stackoverflow.com/questions/15994316/clojure-head-retention का डुप्लिकेट है, जो एक अच्छा जवाब देता है। – robvir

उत्तर

1

Count ओ (1) है। यही कारण है कि आपके माप इस पर निर्भर नहीं हैं।

+1

सूचियों की संख्या वास्तव में ओ (1) है, लेकिन "क्लोजर प्रोग्रामिंग" के अनुसार, सीईसी वास्तव में सूचीबद्ध नहीं हैं और एक सीक की लंबाई प्राप्त करने के लिए लागत होती है। –

+0

क्षमा करें। मैंने तुम्हें गुमराह किया है।हां, आपके मामले में यह LazySeq है और "गिनती" ओ (एन) है। मेरी मशीन पर (गिनती ए) ने 0.01 9 एमसीईसी लिया। तो आपके माप के लिए यह अभी भी ओ (1) जैसा दिखता है। – mobyte

+0

कृपया, जांचने की कोशिश करें (गिनती बी), क्योंकि मेरे मामले में यह (गिनती बी) है, नहीं (ए गिनती है)। –

0

let फॉर्म में बाध्यकारी भी हम इस मूल्य का उपयोग नहीं करते हैं। प्रिंट ऊपर

(let [x (println "Side effect")] 1) 

कोड "साइड प्रभाव", और वापसी 1.

अपने सभी तीन उदाहरण अंदर जाने के रूप में एक ही बंधन का इस्तेमाल किया है, इसलिए मैं कोई फर्क यहाँ नहीं दिख रहा। वैसे, मेरी मशीन पर आपके सभी स्निपेट लगभग बराबर समय लेते थे।

वास्तविक अंतर है जब आप कुछ इस तरह का प्रयास करें:

(time (let [r (range 2e7) 
     a (take 100 r) 
     b (drop 100 r)] 
    [(count a)])) 
"Elapsed time: 0.128304 msecs" 
[100] 

(time (let [r (range 2e7) 
     a (take 100 r) 
     b (drop 100 r)] 
    [(count b)])) 
"Elapsed time: 3807.591342 msecs" 
[19999900] 

तथ्य यह है कि b और a आलसी दृश्यों, O(n) समय में count काम करता हैं के कारण। लेकिन पहले उदाहरण में हम बी के लिए गिनती की गणना नहीं करते हैं, इसलिए यह लगभग तुरंत काम करता है।

+2

को बढ़ाने के लिए कुल समय का कारण बनता है मूल उदाहरणों में' r' 'a' और' b' तुरंत आलसी मूल्यांकन किए गए अनुक्रमों के लिए बयान में बाध्य होते हैं । इन नामों को बाध्य करने से अनुक्रमों का मूल्यांकन नहीं किया जा सकता है। –

+0

@ आर्थरउल्फेल्ड सही, ए और बी आलसी seqs के लिए बाध्य – mishadoff

1

count फ़ंक्शन ओ (1) Counted संग्रहों के लिए है, जिसमें वैक्टर और सूचियां शामिल हैं।

दूसरी ओर, अनुक्रम, not counted हैं जो count ओ (एन) बनाता है। यहां महत्वपूर्ण हिस्सा यह है कि कार्य take-while और drop-while रिटर्न अनुक्रम। तथ्य यह है कि वे भी आलसी हैं यहां एक प्रमुख कारक नहीं है।

1

जब समय एक एक बेंचमार्क का उपयोग कर, परीक्षण एक सटीक परिणाम

user> (defn example2 [] (let [r (range 1e7)            
       a (take-while #(< % 12) r)          
       b (drop-while #(< % 12) r)]       
      [(count a) (count b)])) 
#'user/example2 

user> (dorun (take 1000 (repeatedly example2))) 
nil 

user> (time (example2)) 
"Elapsed time: 614.4 msecs" 
[12 9999988] 

मैं क्रम में विचरण दोष क्योंकि हॉटस्पॉट संकलक अभी तक पूरी तरह उत्पन्न वर्गों optomized है प्राप्त करने के लिए कई बार चलाते हैं। मैं पहले और दूसरे उदाहरण कई बार भाग गया और मिश्रित रिश्तेदार परिणाम मिल गया:

रन उदाहरण एक दो बार:

autotestbed.core> (time (let [r (range 1e7)                 
             a (take-while #(< % 12) r)          
                b (drop-while #(< % 12) r)]       
           [(count a) (count b)])) 
"Elapsed time: 929.681423 msecs"                   
[12 9999988] 
autotestbed.core> (time (let [r (range 1e7)                 
             a (take-while #(< % 12) r)          
                b (drop-while #(< % 12) r)]       
           [(count a) (count b)])) 
"Elapsed time: 887.81269 msecs"                    
[12 9999988] 

तो उदाहरण दो चलाने दो बार:

core> (time (let [r (range 1e7)                 
        a (take-while #(< % 12) r)          
        b (drop-while #(< % 12) r)]       
      [(count a) (count b)])) 
"Elapsed time: 3838.751561 msecs"                   
[12 9999988] 
core> (time (let [r (range 1e7)                 
        a (take-while #(< % 12) r)          
        b (drop-while #(< % 12) r)]       
      [(count a) (count b)])) 
"Elapsed time: 970.397078 msecs"                   
[12 9999988] 

sometiems दूसरा उदाहरण बस

0

जितना समय दिखा रहा है वह पूरी तरह से सिस्टम निर्भर है .... यदि आप इसे फिर से निष्पादित करते हैं, तो यह कुछ अलग दिखाएगा प्रत्येक निष्पादन के लिए समय बीत गया