2014-04-23 2 views
7

क्लोजर शैली (और सामान्य रूप से अच्छी सॉफ्टवेयर इंजीनियरिंग) कई छोटे कार्यों पर जोर देती है, जिनमें से एक उप-समूह बाहरी इंटरफेस प्रदान करने के लिए सार्वजनिक रूप से दिखाई देता है।क्लोजर शैली: defn-vs. letfn

Clojure में वहाँ तरीके यह करने के लिए की एक जोड़ी होने लगते हैं:

(letfn [(private-a ...) 
     (private-b ...)] 
    (defn public-a ...) 
    (defn public-b ...)) 

(defn- private-a ...) 
(defn- private-b ...) 
(defn public-a ...) 
(defn public-b ...) 

letfn प्रपत्र अधिक वर्बोज़ और शायद कम लचीला लगता है, लेकिन यह काम करता है के दायरे कम करता है।

मेरा अनुमान है कि Letfn केवल अन्य रूपों के अंदर उपयोग के लिए है, जब केवल एक छोटे से क्षेत्र में छोटे सहायक कार्यों का उपयोग किया जाता है। क्या यह सर्वसम्मति है? क्या कभी भी शीर्ष स्तर पर उपयोग किया जाना चाहिए (जैसा कि मैंने पहले अनुशंसित देखा है)? इसका इस्तेमाल कब किया जाना चाहिए?

उत्तर

11

letfn आपसी प्रत्यावर्तन के मामलों में उपयोग के लिए करना है के साथ ऐसा नहीं है।

शीर्ष स्तर पर कहीं भी defn मैक्रो का उपयोग न करें जब तक आपके पास बहुत विशिष्ट कारण न हों। इसे def विशेष रूप में विस्तारित किया जाएगा जो वैश्विक var बना और प्रशिक्षित करेगा।

+0

क्या आपको लगता है कि सामान्य रूप से सहायक कार्यों के लिए 'letfn' उपयुक्त नहीं है - उपयोगकर्ता का उपयोग 24244739 का उल्लेख किया गया है - लेकिन केवल पारस्परिक रिकर्सन के लिए? मुझे 'letfn' के साथ सामान्य रूप से क्या किया जाता है, इसके लिए मुझे कोई एहसास नहीं है, इसलिए मैं मूर्खतापूर्ण हो सकता हूं, लेकिन मैं अक्सर' letfn', या कभी-कभी '(चलो [f (fn [x] ...) का उपयोग करके सहायक कार्यों को परिभाषित करता हूं। ..] ''let' और' letfn' का उपयोग करने से बचने के लिए। – Mars

+0

मुझे लगता है कि 'letfn' या' (चलो [f (fn [x] ... 'जैसा कि ठीक है। मैं हमेशा यही करता हूं यह शीर्ष स्तर पर परिभाषित कार्यों की संख्या को कम करता है, जिसे मैं एक अच्छी चीज़ के रूप में देखता हूं। –

+0

स्पष्ट करने के लिए, हालांकि, मैं 'deff' * के भीतर' letfn' * का उपयोग करता हूं। कुछ '(defn top-level-fn [xs] (letfn [(सहायक [y] (y-do-something-y के साथ))] (मानचित्र सहायक xs))) –

4

letfn का उद्देश्य defn फ़ॉर्म के उद्देश्य से बिल्कुल अलग है। शीर्ष स्तर पर letfn का उपयोग करके आपको डीफ़एन की समान गुण नहीं मिलती हैं, क्योंकि letfn के अंदर स्थित कार्यों के किसी भी बाइंडिंग को इसके दायरे से बाहर दिखाई नहीं दे रहा है। let या letfn के अंदर बंधे कार्यों के लिए बाध्यकारी अपने अक्षीय दायरे के बाहर उपलब्ध नहीं है। साथ ही, letfn के अंदर बंधे कार्यों की दृश्यता उस क्रम से स्वतंत्र है जिसमें वे उस शब्दावली के दायरे में बंधे हैं।

(letfn [(is-even? [n] 
      (if (zero? n) 
      true 
      (is-odd? (dec n)))) 
     (is-odd? [n] 
      (if (zero? n) 
      false 
      (is-even? (dec n))))] 
    (is-even? 42)) 

;; => true 

शीर्ष स्तर पर यह प्रयोग न करें: यह let.

+0

@ थंबनेल वर्र्स का उपयोग करने के लिए एक गलत शब्द था। मैंने शर्तों को ठीक करने की कोशिश की। –

2

मेरे नियम ये हैं:

  • एक सहायक समारोह एक सार्वजनिक एक में इस्तेमाल किया जाता है, यह let या letfn साथ स्थानीय रूप से परिभाषित करते हैं।
  • यदि इसका उपयोग कई में किया जाता है, तो इसे defn- के साथ शीर्ष स्तर पर परिभाषित करें।

और

  • शीर्ष स्तर पर let या letfn प्रयोग न करें।
  • शीर्ष स्तर के अलावा कहीं भी def या defn या defn- का उपयोग न करें।
+0

मैं कुछ निजी कार्यों और मेरे बीच संचार की अनुमति देने के लिए एक चैनल का उपयोग करता हूं मुख्य कार्य और उपयोग: '(चलो [सी (चैन)] (defn- a ...) (defn-b ...) (defn -main (a ...) (बी ...))) क्या यह अच्छा नहीं होगा? – peter

+0

@ पीटर मैं नहीं कहूंगा कि अगर आपको वास्तव में उस परिवर्तनशीलता और स्थिति की आवश्यकता है तो यह बहुत बुरा है। चेतावनी दीजिये, यह समवर्तीता के साथ समस्याओं का कारण बन जाएगा। – seequ