2010-08-08 10 views
7

अगर मैं clojureक्लोजर फ़ंक्शन चक्रीय निर्भरताएं विशेष रूप से डिज़ाइन द्वारा अस्वीकृत हैं, या क्या यह केवल एक पाठक व्यवहार है?

(defn sub1a [a] 
    (cond 
    (= a 0) 0 
    true (sub1b (- a 1)))) 

(defn sub1b [a] 
    (cond 
    (= a 0) 0 
    true (sub1a (- a 1)))) 

(println (sub1a 10)) 

में निम्न उपाय अपनाते हैं मैं निम्नलिखित त्रुटि मिलती है:

java.lang.Exception: Unable to resolve symbol: sub1b in this context 

लेकिन अगर मैं निम्न करें:

(defn sub1a [a] 
    (cond 
    (= a 0) 0 
    true (- a 1))) 

(defn sub1b [a] 
    (cond 
    (= a 0) 0 
    true (- a 1))) 

(defn sub1a [a] 
    (cond 
    (= a 0) 0 
    true (sub1b (- a 1)))) 

(defn sub1b [a] 
    (cond 
    (= a 0) 0 
    true (sub1a (- a 1)))) 

(println (sub1a 10)) 

यह ठीक चलाता है।

क्या यह डिज़ाइन द्वारा है, या क्लोजर रीडर के तरीके से केवल एक फ़ंक्शन काम करता है?

उत्तर

16

आप क्या कर सकते हैं

(declare sub1a sub1b) 

'घोषित' विशेष रूप से आगे घोषणाओं करने के लिए कोई बाइंडिंग के साथ एक वर बनाने के लिए है।

(defn sub1a [a] 
    (cond 
    (= a 0) 0 
    true (sub1b (- a 1)))) 

(defn sub1b [a] 
    (cond 
    (= a 0) 0 
    true (sub1a (- a 1)))) 

(println (sub1a 10)) 

इसके अलावा cond में (clojure के लिए) डिफ़ॉल्ट शर्त निर्दिष्ट करने के लिए idomatic तरह से उपयोग कर रहा है:

एक आप के नाम की घोषणा की और कुछ खंड। यह सामान्य लिस्प से थोड़ा अलग है जो टी (सत्य के लिए) का उपयोग करता है। तो आपके पिछले कोड को फिर से लिखा जा सकता है:

(defn sub1a [a] 
    (cond 
    (= a 0) 0 
    :else (sub1b (- a 1)))) 

... 
3

सही समाधान आरकेकृष्णन द्वारा पोस्ट किया गया है।

प्रश्न के इस हिस्से के लिए के रूप में:

Is this by design, or just a function of the way the Clojure reader works?

वास्तव में इस Clojure पाठक के साथ कुछ नहीं है - क्योंकि संकलक तुरंत उन्हें (का सामना उन स्थितियों में जहां वे पर Vars के प्रतीकों को हल करता है यह "आखिरकार" को एक वर के लिए हल करने की आवश्यकता है, जहां उन स्थानों के विपरीत जहां वे स्थानीय नाम हैं, उद्धृत या विशेष रूप से या एक मैक्रो को पास कर दिए जाते हैं)। यह दक्षता के कारणों के लिए समझ में आता है: यह जानने के लिए कि कौन सा प्रतीक एक प्रतीक को संकलित समय पर संदर्भित करता है, जिससे कोड उत्पन्न करना संभव हो जाता है, जिसे रनटाइम पर प्रतीकों को हल करने की आवश्यकता नहीं होती है (इसे अभी भी सामान्यतः मान वर्र्स के मूल्यों को देखने की आवश्यकता है, लेकिन नहीं स्वयं स्वयं)। क्या तुम सच में करना चाहता था, तो आप क्रम में अपने कोड संकल्प प्रतीक हो सकता है:

(defn sub1a [a] 
    (cond 
    (= a 0) 0 
    :else ((resolve 'sub1b) (- a 1)))) 

(defn sub1b [a] 
    (cond 
    (= a 0) 0 
    :else ((resolve 'sub1a) (- a 1)))) 

(println (sub1a 10)) 

; prints 0 and returns nil 

यह है, तथापि, प्रदर्शन में एक निश्चित गिरावट जो शायद ही कभी वास्तविक कोड में उचित है, कारण, इस प्रकार Clojure आप बारे में स्पष्ट होना बनाता है यदि आप वास्तव में सोचें कि यह वही है जो आप चाहते हैं।