12

मैं स्टुअर्ट हेलोवे की पुस्तक प्रोग्रामिंग क्लोजर के माध्यम से काम करने की कोशिश कर रहा हूं। यह पूरी कार्यात्मक सामग्री मेरे लिए बहुत नई है।क्लोजर फ़ंक्शन (एनटी [कॉल इंडेक्स]) और संरचना (अंतिम (इंडेक्स कॉल लेना) के बीच क्या अंतर है)

मैं समझता हूँ कि कैसे

(defn fibo[] 
    (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1]))) 

फाइबोनैचि अनुक्रम lazily उत्पन्न करता है। मुझे समझ नहीं आता क्यों

(last (take 1000000 (fibo))) 

काम करता है, जबकि

(nth (fibo) 1000000) 

एक OutOfMemoryError फेंकता है। क्या कोई यह बता सकता है कि ये दो अभिव्यक्ति कैसे भिन्न हैं? क्या (एनएच) किसी भी तरह अनुक्रम के सिर पर पकड़ रहा है?

धन्यवाद!

+1

न तो इन काम के: 1.3.0 में ठीक से काम करने के लिए अपने FIBO प्राप्त करने के लिए आप गणित कार्यों कि bignums को संख्या को बढ़ावा देंगे उपयोग करने के लिए की जरूरत है।कॉम के रूप में संख्या इतनी बड़ी है कि यह एक अतिप्रवाह का कारण बनता है। AFAICT आप किसी भी चीज़ का संदर्भ नहीं रखते हैं इसलिए मुझे विश्वास नहीं है कि "सिर पर पकड़ना" है। क्या आपको यकीन है कि यह सिर्फ इसलिए नहीं है क्योंकि संख्या इतनी बड़ी है कि बड़ी संख्या में क्या है? –

+0

अंतिम कार्यान्वयन एक सीधी आगे ओ (एन) पूंछ-पुनरावर्ती कार्यान्वयन है, और यह किसी भी चीज़ पर नहीं है। एनएच जावा में लागू किया गया है और मुझे पूरा यकीन है कि यह किसी भी चीज़ पर नहीं है। इसलिए, आपके दोनों अनुक्रमों को ठीक काम करना चाहिए (सिद्धांत में)। एकमात्र चीज जिसे मैं सोच सकता हूं, हालांकि मैं इस पर स्पष्ट नहीं हूं परिणाम को प्रभावित करता है, यह है कि आपकी एनटी कॉल वास्तव में आपके अंतिम कॉल की तुलना में 1 आइटम की गणना करती है। nth 1000000 = 1000001st आइटम (0 अनुक्रमण) – vedang

+0

@vedang धन्यवाद ... मैं उस महत्वपूर्ण भेद को नहीं पकड़ा होता। यह मेरी समस्या का स्रोत नहीं था, हालांकि मुझे एहसास नहीं हुआ था कि लेने का तर्क अनुक्रम का आकार है, जबकि एनएच के लिए तर्क सूचकांक है। – Josh

उत्तर

4

मुझे लगता है कि आप google group में चर्चा की गई समस्या के बारे में बात कर रहे हैं और रिच हिकी ने patch प्रदान किया जो समस्या को हल करता है। और पुस्तक, बाद में प्रकाशित किया गया था, इस विषय को शामिल नहीं किया था।

clojure 1.3 में nth उदाहरण fibo फ़ंक्शन में मामूली सुधार के साथ काम करता है। अब, 1.3 में बदलावों के कारण, हमें मनमानी परिशुद्धता का उपयोग करने के लिए M स्पष्ट रूप से ध्वजांकित करना चाहिए, या यह throwIntOverflow के साथ आता है।

(defn fibo[] 
    (map first (iterate (fn [[a b]] [b (+ a b)]) [0M 1M]))) 

और इन परिवर्तनों

(nth (fibo) 1000000) 

सफल होने के साथ

+0

मैं पुस्तक, 1.1.0-अल्फा-स्नैपशॉट के साथ वितरित एक स्नैपशॉट संस्करण का उपयोग कर रहा था। 1.3.0 में बदलना काम किया। मैं उस संस्करण का अनुमान लगा रहा हूं जिसमें मैंने उस बग को शामिल किया था जिसका आप उल्लेख करते हैं ... अर्थात् "हाल ही में ऑप्टिमाइज़ेशन प्रयास ने RT.nth में एक हेड-रिटेनिंग हॉप पेश किया" – Josh

+0

"एम" हालांकि आवश्यक नहीं था। लगता है कि क्लोजर कम से कम 1.3.0 के साथ, BigInt में परिवर्तित हो रहा है। – Josh

+0

@ जोश, मेरी मशीन पर नहीं। मेरा जवाब देखें –

1

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

(defn fibo[] 
    (map first (iterate (fn [[a b]] [b (+ a b)]) [(bigint 0) 1]))) 

के लिए मैं दोनों भाव के लिए सही परिणाम प्राप्त (एक बहुत बड़ा पूर्णांक ...)।

0

मुझे लगता है कि आप अपने मशीन के लिए एक विशेष स्मृति सीमा तक पहुंच गए हो सकता है, और नहीं एक वास्तविक अंतर (यदि आपके पास पर्याप्त स्मृति है तो) समारोह में।

https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java में एनएच के लिए स्रोत कोड को देखते हुए यह किसी भी तरह की नहीं दिखता है या सिर को बनाए रखता है।

हालांकि, एनएच आइटम संख्या द्वारा गिनती के बजाए शून्य-आधारित अनुक्रमण का उपयोग करता है। एनएच के साथ आपका कोड अनुक्रम का 1000001 वां तत्व (इंडेक्स 1000000 पर एक) का चयन करता है। आप ले जाने के साथ कोड 1000000 तत्व अनुक्रम में अंतिम तत्व लौट रहा है। इंडेक्स 99 99 99 के साथ यह आइटम है। यह देखते हुए कि कितनी तेजी से फाइब बढ़ता है, वह आखिरी वस्तु ऊंट की पीठ तोड़ सकती है।

इसके अलावा, मैं 1.3.0 स्रोत की जांच कर रहा था। शायद पहले के संस्करणों में अलग-अलग कार्यान्वयन थे। tryclj पर मेरे लिए

(defn fibo[] 
    (map first (iterate (fn [[a b]] [b (+' a b)]) [0 1]))) 
संबंधित मुद्दे