2010-08-10 10 views
7

में ढेर और कचरे के बारे में शुरुआती प्रश्न मेरे पास क्लोजर: के बारे में एक प्रश्न है, मैं Project Euler से जाकर भाषा सीखने की कोशिश कर रहा हूं और मुझे समझ में नहीं आता कि हुड के नीचे क्या चल रहा है: निम्न कोड को डिज़ाइन किया गया है lim तक सभी प्राइम संख्याओं की एक सूची लौटाएं। मुझे लगता है कि यह हेप-स्पेस में ओ (एन) होना चाहिए क्योंकि मैं lim तक सभी संख्याओं की एक सूची बना देता हूं, और फिर पहली बार एक नई सूची में स्थानांतरित करते समय उन्हें एक-एक करके फ़िल्टर करता हूं। (मुझे पता है कि मैं वास्तव में प्रत्येक पुनरावृत्ति होना नई सूची बनाने रहा हूं, लेकिन मुझे नहीं लगता था कि वे अधिक स्मृति ले जाएगा?) वैसे भी मैंक्लोजर

(defn getAllPrimes [lim] 
    (defn getPrimes [primes numlist] 
    (if (not-empty numlist) ;base case; 
    (recur (cons (first numlist) primes) ;put the prime on to the prime list 
      (filter 
     (fn [x] (not (div? x (first numlist)))) ;remove the prime and all its multiples from the numlist 
     (rest numlist))) 
     primes)); return the primes 
    (getPrimes() (range 2 lim))) ;call the recursive function with and empty prime list to be filled up and a full numlist to be emptied 

के साथ इस चला रहा हूँ और मैं ढेर में स्थान कम है, जब मैं फोन रखने के

(apply + (getAllPrimes 2000000)) 

, लेकिन मैं

(apply + (filter even? (range 2000000))) 

पर स्थान शेष नहीं नहीं है तो मुझे लगता है कि मुझे समझ में नहीं चाहिए कि कैसे सूचियों कचरा कॉल में एकत्र कर रहे पुनरावृत्ति होना है और वास्तव में हे उपयोग कर रहा हूँ (एन * एन) ढेर या कुछ।

+2

यह पहले से यहां उत्तर है: संक्षिप्त जवाब यह है कि फ़िल्टर आलसी अनुक्रम बनाता है और आप फिल्टर पर फ़िल्टर को कॉल कर रहे हैं ... और आखिरकार ओवरफ्लो ढेर करते हैं। इसे हल करने का एक तरीका (जैसा कि ड्रेश द्वारा सुझाया गया है) को 'डोल' द्वारा हर कदम अनुक्रम का एहसास करना है। –

उत्तर

6

मेरा मानना ​​है कि समस्या यह है कि प्रत्येक पुनरावर्ती के साथ, आप एक नया आलसी अनुक्रम बना रहे हैं, जो कि आखिरी बार संदर्भित करता है, इसलिए कुछ पुनरावृत्तियों के बाद आप एक सीक धारण कर रहे हैं जिसमें एक सीक का सिर होता है जो सिर रखता है एक सीक का सिर जो एक सीक के सिर रखता है। ... सभी मध्यवर्ती seqs आपके ढेर भर रहे हैं।

हालांकि एक प्रमुख चलनी लिखना एक सार्थक व्यायाम है, यदि आप उत्तर प्राप्त करना चाहते हैं, तो क्लोजर में इसकी मानक लाइब्रेरी में प्राइम संख्याओं का अनुक्रम शामिल है: clojure.contrib.lazy-seqs/primes। इस लंबवत यूलर समस्या का मानक समाधान एक-लाइनर है।

एक शैली बिंदु के रूप में, एक आंतरिक defn एक अच्छा विचार नहीं है। व्यावहारिक प्रभाव वही है जैसे डीफ़एन शीर्ष स्तर पर थे, लेकिन अगर मुझे गलत नहीं लगता है, तो हर बार प्राप्त होने पर var को फिर से सौंप दिया जाता है, और रनटाइम पर वर्रों को फिर से परिभाषित करना बहुत दृढ़ता से निराश होता है। चूंकि कोड सिर्फ एक var को परिभाषित कर रहा है, इसलिए GetPrimes अभी भी GetAllPrimes के रूप में दिखाई देने वाला है। इस मामले में, GetPrimes को लूप/रिकर के रूप में आसानी से फिर से लिखा जा सकता है जिसमें कोई भी आंतरिक फ़ंक्शन, अज्ञात या नाम नहीं है। यही कारण है कि अपने श्रृंखला के- आलसी-seqs समस्या मदद नहीं करता है, लेकिन यह कोड थोड़ा और मानक दिखने पड़ता है:

(defn getAllPrimes [lim] 
    (loop [primes() 
     numlist (range 2 lim)] 
    (if (not-empty numlist) 
     (recur (cons (first numlist) primes) 
      (filter (fn [x] (not (div? x (first numlist)))) 
        (rest numlist))) 
     primes))) 

मैं भी CamelCase के उपयोग से बचने होगा। इस समारोह के लिए क्लोजर मानक नाम प्राप्त-सब-प्राइम्स होगा।

व्यावहारिक समस्या पर वापस आना, हालांकि, कम से कम काम जो आप अपना कोड काम करने के लिए कर सकते हैं, प्रत्येक पुनरावृत्ति पर प्रत्येक सीईसी को मजबूर करना होगा, यानी, अपने फ़िल्टर कॉल को डोल में लपेटें। मैं इस की कोशिश की, और जब तक यह अभी भी बहुत धीरे चलता है, यह कम से कम ढेर से बाहर चलने के बिना पूरा होने से चलती है:

(defn get-all-primes [lim] 
    (loop [primes() 
     numlist (range 2 lim)] 
    (if (not-empty numlist) 
     (recur (cons (first numlist) primes) 
      (doall (filter #(not (div? % (first numlist))) 
          (rest numlist)))) 
     primes))) 
+1

धन्यवाद, मैं उत्तर और स्टाइल पॉइंटर्स की भी सराहना करता हूं। वह बहुत उपयोगी था। मैं आंतरिक defn के साथ बहुत सारे काम लिख रहा हूं और मैं भविष्य में लूप का उपयोग करूंगा। –

+1

मैं पुस्तकालय में प्राइम फ़ंक्शन के बारे में भी जानता था लेकिन तब मुझे नहीं पता था कि फ़िल्टर कैसे काम करता है और मुझे ऐसा करने की ज़रूरत क्यों है :)। –