मेरे पास एक निश्चित "तथ्यात्मक" संपत्ति के साथ किसी संख्या की गणना करने के लिए निम्न क्लोजर कोड है। (कोड वास्तव में क्या करता है माध्यमिक है)।पूंछ-पुनरावर्ती कार्य भी तेज नहीं होना चाहिए?
(defn factor-9
([]
(let [digits (take 9 (iterate #(inc %) 1))
nums (map (fn [x] ,(Integer. (apply str x))) (permutations digits))]
(some (fn [x] (and (factor-9 x) x)) nums)))
([n]
(or
(= 1 (count (str n)))
(and (divisible-by-length n) (factor-9 (quot n 10))))))
अब, मैं TCO में हूँ और महसूस करते हैं कि Clojure केवल पूंछ-प्रत्यावर्तन प्रदान कर सकते हैं स्पष्ट रूप से ऐसा recur
कीवर्ड का उपयोग बताया। तो मुझे लगता है कि (पुनरावृत्ति होना फर्क सिर्फ इतना होने के साथ कारक-9 की जगह) करने के लिए कोड फिर से लिख दिया:
(defn factor-9
([]
(let [digits (take 9 (iterate #(inc %) 1))
nums (map (fn [x] ,(Integer. (apply str x))) (permutations digits))]
(some (fn [x] (and (factor-9 x) x)) nums)))
([n]
(or
(= 1 (count (str n)))
(and (divisible-by-length n) (recur (quot n 10))))))
मेरी जानकारी के लिए, TCO एक डबल लाभ है। पहला यह है कि यह स्टैक को गैर पूंछ-रिकर्सिव कॉल के रूप में भारी रूप से उपयोग नहीं करता है और इस प्रकार इसे बड़े रिकर्सन पर नहीं उड़ाता है। दूसरा, मुझे लगता है कि परिणामस्वरूप यह तेज़ है क्योंकि इसे लूप में परिवर्तित किया जा सकता है।
अब, मैंने बहुत मोटा बेंचमार्क बनाया है और हालांकि दो कार्यान्वयन के बीच कोई अंतर नहीं देखा है। क्या मैं अपनी दूसरी धारणा में गलत हूं या क्या इसे प्राप्त करने के लिए एक चाल का उपयोग कर JVM (जिसमें स्वचालित टीसीओ नहीं है) और recur
पर चलने के साथ कुछ करना है?
धन्यवाद।
यह दिलचस्प है, मैंने कारक 9 को मापने के लिए मानदंड स्थापित किया है और पाया कि टीसीओ संस्करण वास्तव में गैर-अनुकूलित संस्करण की तुलना में कुछ हद तक धीमा है। Https://gist.github.com/773060 देखें। –
आश्चर्यजनक रूप से (मेरे लिए कम से कम :)) एक साधारण फिबोनाकी गणना के लिए दो संस्करणों की तुलना करते समय अंतर की दुनिया है: https://gist.github.com/773068 –
यह नाटकीय है, है ना? बेंचमार्क की खुशी। कम से कम आपके पास एक दृढ़ तर्क है कि टीसीओ एक बड़ा अंतर बनाता है :-) – hutch