2012-05-11 19 views
15
(take 2 (for [x (range 10) 
       :let [_ (println x)] 
       :when (even? x)] x)) 
>> (* 0 
* 1 
* 2 
* 3 
* 4 
* 5 
* 6 
* 7 
* 8 
* 9 
0 2) 

मुझे लगता है कि मैं सिर्फ उल्लेखनीय घना था। लेकिन नहीं, यह पता चला है कि क्लोजर वास्तव में किसी भी आलसी अनुक्रम (यदि उपलब्ध हो) के पहले 32 तत्वों का मूल्यांकन करता है। आउच।क्या 'के लिए' वास्तव में क्लोजर में आलसी नहीं है?

मेरे पास :let में एक रिकर्सिव कॉल के साथ for था। मैं बहुत उत्सुक था कि गणना पहली बार गहराई से पहले चौड़ाई में क्यों चल रही थी। ऐसा लगता है कि गणना (हालांकि, निष्पक्ष होना, स्मृति नहीं) विस्फोटक था क्योंकि मैं रिकर्सिव पेड़ की सभी ऊपरी शाखाओं को नीचे रखता था। क्लोजर का 32-चंकिंग चौड़ाई पहले मूल्यांकन को मजबूर कर रहा था, भले ही कोड का तार्किक इरादा पहले गहराई से था।

वैसे भी, क्या आलसी दृश्यों के 32-चंकिंग के बजाय 1-चंकिंग को मजबूर करने का कोई आसान तरीका है?

उत्तर

13

माइकस फोगस has written a blog entry on disabling this behavior by providing a custom ISeq implementation

the modified version by Colin Jones से बेशर्म चोरी करने के लिए:

(defn seq1 [#^clojure.lang.ISeq s] 
    (reify clojure.lang.ISeq 
    (first [_] (.first s)) 
    (more [_] (seq1 (.more s))) 
    (next [_] (let [sn (.next s)] (and sn (seq1 sn)))) 
    (seq [_] (let [ss (.seq s)] (and ss (seq1 ss)))) 
    (count [_] (.count s)) 
    (cons [_ o] (.cons s o)) 
    (empty [_] (.empty s)) 
    (equiv [_ o] (.equiv s o)))) 

एक सरल तरीका in The Joy of Clojure दिया जाता है:

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

धन्यवाद! यह मुझे दो घंटों तक फंस गया था। मुझे पता नहीं लगा कि (1 ले लो (कुछ मजेदार [1 2 3 4] मानचित्र)) सभी 4 तत्वों के लिए कुछ-func का मूल्यांकन करता है ... मुझे कहना होगा, यह स्पष्ट नहीं था कि यह क्यों हो रहा था, "मानचित्र" और "टेक" पर दस्तावेज़ पढ़ने से –

3

अपने शीर्षक में सवाल का जवाब करने के लिए, नहीं, for नहीं आलसी है। However, यह:

एक या अधिक बंधन फार्म/संग्रह-expr जोड़े का एक वेक्टर, प्रत्येक शून्य या अधिक संशोधक द्वारा पीछा किया जाता है, और expr के मूल्यांकन की आलसी अनुक्रम अर्जित करता है।

(जोर मेरा)

तो what's going on?

मूल रूप से क्लोजर हमेशा सख्ती से मूल्यांकन करता है। आलसी seqs मूल रूप से एक ही चाल का उपयोग उनके जेनरेटर आदि के साथ पाइथन के रूप में करते हैं। आलसी कपड़े में सख्त evals।

दूसरे शब्दों में, forबेसब्री रिटर्न एक आलसी अनुक्रम। जब तक आप इसकी मांग नहीं करेंगे तब तक मूल्यांकन नहीं किया जाएगा, और चकित हो जाएगा।