17

मैं पूंछ रिकर्सन का उपयोग किये बिना किसी अज्ञात फ़ंक्शन में रिकर्सन कैसे करूं?अज्ञात एफएन में रिकर्सन कैसे करें, पूंछ रिकर्सन के बिना

उदाहरण के लिए (Vanderhart 2010, पी 38 से):

(defn power 
    [number exponent] 
    (if (zero? exponent) 
    1 
    (* number (power number (- exponent 1))))) 

चलो कहते हैं कि मैं एक गुमनाम समारोह के रूप में यह करना चाहता था करते हैं। और किसी कारण से मैं पूंछ रिकर्सन का उपयोग नहीं करना चाहता था। मैं यह कैसे करूंगा? उदाहरण के लिए:

((fn [number exponent] ......))))) 5 3) 
125 

मैं इसके लिए पाश उपयोग कर सकते हैं, या पाश केवल साथ प्रयोग किया जा सकता है पुनरावृत्ति होना?

उत्तर

41

fn विशेष रूप आप option to provide a name कि प्रत्यावर्तन के लिए आंतरिक रूप से इस्तेमाल किया जा सकता देता है।

(doc fn) 
;=> (fn name? [params*] exprs*) 

तो, अपना उदाहरण पूरा करने के लिए नाम के रूप में "पावर" जोड़ें।

(fn power [n e] 
    (if (zero? e) 
    1 
    (* n (power n (dec e))))) 

भले ही रिकवरी पूंछ की स्थिति में हुई हो, फिर भी यह मौजूदा स्टैक फ्रेम को प्रतिस्थापित करने के लिए अनुकूलित नहीं किया जाएगा। क्लोजर आपको loop/recur और trampoline के साथ इसके बारे में स्पष्ट होने के लिए मजबूर करता है।

+1

धन्यवाद जेरेमी, मुझे नाम विकल्प के बारे में पता नहीं था। मैं [4clojure] (http://www.4clojure.com/) प्रश्नों के माध्यम से काम कर रहा हूं और वे defn की अनुमति नहीं देते हैं। टेल रिकर्सन स्पष्ट रूप से बेहतर है, लेकिन मैं दौड़ने से पहले चलना चाहता हूं :) –

16

मुझे पता है कि क्लोजर में अज्ञात फ़ंक्शन "नामकरण" के लिए वाक्य रचनात्मक समर्थन है, जैसा कि अन्य उत्तरों ने इंगित किया है। हालांकि, मैं प्रश्न को हल करने के लिए एक प्रथम सिद्धांत दृष्टिकोण दिखाना चाहता हूं, जो प्रोग्रामिंग भाषा पर विशेष वाक्यविन्यास के अस्तित्व पर निर्भर नहीं है और यह पहली ऑर्डर प्रक्रियाओं (लैम्बडास) वाली किसी भी भाषा पर काम करेगा।

सिद्धांत रूप में, यदि आप एक पुनरावर्ती समारोह कॉल करना चाहते हैं, तो आप फ़ंक्शन का नाम तो "गुमनाम" का उल्लेख करने की जरूरत है (यानी बेनाम कार्यों) एक प्रत्यावर्तन के प्रदर्शन के लिए इस्तेमाल नहीं किया जा सकता है ... जब तक आप Y-Combinator का उपयोग करते हैं। Here यह एक स्पष्टीकरण है कि यह क्लोजर में कैसे काम करता है।

मुझे आपको दिखाएं कि इसका उपयोग उदाहरण के साथ कैसे किया जाता है। सबसे पहले, एक Y-Combinator तर्क के परिवर्तनशील साथ कार्यों के लिए काम करता है कि:

(defn Y [f] 
    ((fn [x] (x x)) 
    (fn [x] 
     (f (fn [& args] 
       (apply (x x) args)))))) 

अब, गुमनाम समारोह है कि power प्रक्रिया के रूप में प्रश्न में परिभाषित लागू करता है। जाहिर है, यह एक नाम नहीं है, power सबसे बाहरी कार्य करने के लिए केवल एक पैरामीटर है:

(fn [power] 
     (fn [number exponent] 
      (if (zero? exponent) 
       1 
       (* number (power number (- exponent 1)))))) 

अंत में, यहाँ कैसे गुमनाम power प्रक्रिया को Y-Combinator लागू करने के लिए, पैरामीटर के रूप में पारित करने है number=5 और exponent=3 (यह नहीं है पूंछ पुनरावर्ती BTW):

((Y 
    (fn [power] 
     (fn [number exponent] 
      (if (zero? exponent) 
       1 
       (* number (power number (- exponent 1))))))) 
5 3) 

> 125 
+3

ग्रेसीस ऑस्कर। वाई-कॉम्बिनेटर बहुत दिलचस्प लग रहा है - मैं इसे और अधिक पढ़ने जा रहा हूं! –

+0

वाई संयोजक को समझने के लिए एक और अच्छा स्रोत है [द लिटिल शेमर] (https://mitpress.mit.edu/books/little-schemer)। – Mars

3

fnoptional name argument लेता है जिसका उपयोग फ़ंक्शन को बार-बार कॉल करने के लिए किया जा सकता है।

उदा।:

user> ((fn fact [x] 
      (if (= x 0) 
       1 
       (* x (fact (dec x))))) 
     5) 
;; ==> 120 
+0

धन्यवाद ग्रेग, ऐसा लगता है कि नाम विकल्प जाने का तरीका है। –

2

हाँ आप इस के लिए loop उपयोग कर सकते हैं। दोनों loop रों में recur काम करता है और fn रों

user> (loop [result 5 x 1] (if (= x 3) result (recur (* result 5) (inc x)))) 
125 

एक idomatic clojure समाधान इस तरह दिखता है:

user> (reduce * (take 3 (repeat 5))) 
125 

या का उपयोग करता Math.pow() ;-)

user> (java.lang.Math/pow 5 3) 
125.0 
+0

लेकिन सवाल "पूंछ रिकर्सिंग किए बिना" था :-) –

0

loop कर सकते हैं एक पुनरावर्ती लक्ष्य बनें, ताकि आप इसे भी कर सकें।

+0

लेकिन सवाल "पूंछ रिकर्सिंग किए बिना" था :-) –

+0

:-) मुझे पता है, लेकिन पुनरावृत्ति रिकर्सन नहीं करता है, संकलक आपके लिए एक लूप फिक्स करेगा (पूंछ रिकर्सन स्थिति में भी)। तो तरह नहीं। – Bill

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