2010-05-15 13 views
9

मेरे पास नेस्टेड डोसक लूप के बारे में कोई प्रश्न है। प्रारंभ समारोह में, एक बार मुझे एक जवाब मिल जाने पर मैंने परमाणु को सत्य पर सेट किया, ताकि बाहरी लूप सत्यापन के साथ: विफल हो जाए। हालांकि ऐसा लगता है कि यह इसे तोड़ता नहीं है, और लूप चलते रहते हैं। इसके साथ गलत क्या है?नेस्टेड डोसेक से कैसे बाहर निकलना है

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

(def pentagonal-list (map (fn [a] (/ (* a (dec (* 3 a))) 2)) (iterate inc 1))) 


(def found (atom false)) 


(defn pentagonal? [a] 
    (let [y (/ (inc (Math/sqrt (inc (* 24 a)))) 6) 
     x (mod (* 10 y) 10)] 
    (if (zero? x) 
    true 
    false))) 


(defn both-pent? [a b] 
    (let [sum (+ b a) 
     diff (- a b)] 
    (if (and (pentagonal? sum) (pentagonal? diff)) 
     true 
     false))) 

(defn start [] 
(doseq [x pentagonal-list :while (false? @found)] 
    (doseq [y pentagonal-list :while (<= y x)] 
     (if (both-pent? x y) 
      (do 
      (reset! found true) 
      (println (- x y))))))) 

उत्तर

13

यहां तक ​​कि एक बार परमाणु true के लिए सेट है, अपने संस्करण नहीं भीतरी doseq खत्म जब तक चलना बंद कर देते (y जब तक> x)। आंतरिक लूप खत्म होने के बाद यह बाहरी पाश को समाप्त कर देगा। आखिरकार जब मैं इसे चलाता हूं तो यह समाप्त हो जाता है। सुनिश्चित नहीं है कि आप क्या देख रहे हैं।

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

user> (doseq [x (range 0 2) y (range 3 6)] (prn [x y])) 
[0 3] 
[0 4] 
[0 5] 
[1 3] 
[1 4] 
[1 5] 

(एक ही for का सच है।) वहाँ नेस्टेड doseqs है कि मैं के बारे में पता की "बाहर तोड़ने", को छोड़कर throw/catch के लिए कोई तंत्र है, लेकिन यह नहीं बल्कि गैर-मुहावरेदार है। इसके लिए आपको परमाणुओं या doseq की आवश्यकता नहीं है।

(def answers (filter (fn [[x y]] (both-pent? x y)) 
        (for [x pentagonal-list 
          y pentagonal-list :while (<= y x)] 
         [x y]))) 

आपका कोड शैली में बहुत जरूरी है। "इन सूचियों पर लूप करें, फिर मानों का परीक्षण करें, फिर कुछ प्रिंट करें, फिर लूपिंग रोकें।" इस तरह के नियंत्रण के लिए परमाणुओं का उपयोग क्लोजर में बहुत मूर्ख नहीं है।

एक अधिक कार्यात्मक तरीका एक सेक (पेंटगोनल-लिस्ट) लेना और इसे उन कार्यों में लपेटना है जो इसे अन्य seqs में बदल देते हैं जब तक कि आपको एक सीईसी न मिल जाए जो आपको वह चाहिए जो आपको चाहिए। सबसे पहले मैं for का उपयोग इस सीक की दो प्रतियों को जोड़े के एक वर्ग में बदलने के लिए करता हूं जहां y < = x। फिर मैं filter का उपयोग उस सीईसी को उस मूल्य में बदलने के लिए करता हूं जो उन मूल्यों को फ़िल्टर करता है जिनकी हमें परवाह नहीं है।

filter और for आलसी हैं, इसलिए first मान्य मान मिलने पर यह चलना बंद हो जाएगा, यदि कोई आप चाहते हैं। यह आपके इच्छित दो नंबर लौटाता है, और फिर आप उन्हें घटा सकते हैं।

(apply - (first answers)) 

या आप आगे आप के लिए अंतर की गणना करने के लिए एक और map में समारोह लपेट कर सकते हैं।

(def answers2 (map #(apply - %) answers)) 
(first answers2) 

इस तरह से प्रोग्रामिंग के लिए कुछ फायदे हैं। seq कैश किया गया है (यदि आप सिर पर पकड़ की तरह मैं यहाँ करते हैं), इसलिए एक बार एक मूल्य की गणना की जाती है, यह इसके याद रखता है और आप तब से तुरन्त पहुँच सकते हैं। आपका संस्करण परमाणु रीसेट किए बिना फिर से चलाने के नहीं किया जा सकता है, और फिर सब कुछ फिर से गणना करने के लिए होगा। मेरे संस्करण के साथ आप पहले 5 परिणाम प्राप्त करने के लिए (take 5 answers) कर सकते हैं, या यदि आप चाहें तो अन्य चीजों को करने के परिणामस्वरूप मानचित्र पर जा सकते हैं। आप doseq पर इसके ऊपर और मूल्य प्रिंट कर सकते हैं। आदि आदि

मुझे यकीन है कि वहाँ अन्य (शायद बेहतर) तरीके एक परमाणु का उपयोग किए बिना यह अभी भी करने के लिए कर रहे हैं रहा हूँ। आप आम तौर पर संदर्भ परिवर्तनशील जब तक यह 100% Clojure में आवश्यक है से बचना चाहिए।

परमाणु/एजेंट/रेफ को बदलने के लिए फ़ंक्शन नाम शायद अलग हैं क्योंकि यांत्रिकी समान नहीं हैं। रेफरी सिंक्रोनस और लेनदेन के माध्यम से समन्वयित हैं। एजेंट असीमित हैं। परमाणु तुल्यकालिक और असंगठित हैं। वे सभी प्रकार के "संदर्भ को बदलते हैं", और शायद किसी प्रकार का सुपर-फ़ंक्शन या मैक्रो उन्हें सभी नामों में लपेट सकता है, लेकिन यह इस तथ्य को अस्पष्ट कर देगा कि वे हुड के नीचे भारी रूप से अलग-अलग चीजें कर रहे हैं। मतभेदों को पूरी तरह समझाते हुए शायद एसओ पोस्ट के दायरे से परे है, लेकिन http://clojure.org मतभेदों की सभी बारीकियों को पूरी तरह से समझाता है।

+0

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

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