2012-10-08 14 views
8

मुझे एहसास है कि निम्नलिखित कारणों से निम्नलिखित एक बुरा विचार है। मुझे यह भी एहसास हुआ कि मेरे पास 23 का स्टैक ओवरफ्लो प्रतिनिधि है, यह प्रकृति है कि मैं प्रोग्राम के लिए एक नया सीख रहा हूं। हालांकि, कृपया मुझे हास्य दें, और "आप ऐसा क्यों करना चाहते हैं" के बजाय "हम यह कैसे कर सकते हैं" पर ध्यान केंद्रित करें।क्लोजर गतिशील बाध्यकारी

मुझे क्या करना चाहते हैं:

(def dog (Dog. ...)) 
(def cat (Cat. ...)) 

(with-animal dog 
    (println (str "Dog: " (speak) "\n"))) 
(with-animal cat 
    (println (str "Cat: " (speak) "\n"))) 

उत्पादन के लिए:

Dog: woof 
Cat: meow 

तो बुनियादी तौर पर, मैं साथ-पशुचाहते एक मैक्रो s.t. होने के लिए "बोलने" फ़ंक्शन कॉल के सभी अवसरों को उस ऑब्जेक्ट में मैप किया जाता है जिसे मैं ब्लॉक के साथ कॉल कर रहा हूं।

विशेष रूप से, मैं नहीं चाहता कि लिखना चाहते हैं:

(let-binding [speak (fn [] "woof")] ...) 
(let-binding [speak (fn [] "meow")] ...) 

बल्कि, मैं चाहता हूँ के साथ-पशु बनाने के लिए बात समारोह नक्शा वस्तु के साथ मैं फोन कर रहा हूँ करने के कुछ तरीके हैं।

क्लोजर में ऐसा करने का कोई साफ तरीका है?

धन्यवाद!

+1

प्रोटोकॉल का उपयोग क्यों नहीं करते? – DanLebrero

+0

मुझे अस्वीकरण पसंद आया :) – szymanowski

उत्तर

20

गतिशील बाध्यकारी एक कारण के लिए मौजूद है और इसमें बहुत सारे उपयोग हैं, इसलिए इसे समझने के लिए आग लगने के बारे में कोई चिंता नहीं है :-) कुछ पुराने क्लोजर ट्यूटोरियल के आसपास कुछ भ्रम है जो जोड़ने की आवश्यकता को पूर्व-तारीख है ^: गतिशील मेटाडेटा को वर्र्स जिन्हें आप गतिशील रूप से पुनर्निर्मित करने की अपेक्षा करते हैं।

यह पहला उदाहरण मौजूदा नाम को पुन: जोड़कर गतिशील बाध्यकारी का उपयोग करता है।


पहले, कुछ जानवरों बनाने मैं तो बस इस उदाहरण में नक्शे का उपयोग करें, बहुत से लोगों को वस्तु के कुछ अन्य प्रकार का उपयोग करेगा:: इस मैक्रो के लिए की जरूरत है एक नया प्रतीक पेश करने को हटा

(def dog {:sound #(str "wooooof")}) 
(def cat {:sound #(str "mewwww")}) 

समारोह को परिभाषित हम

(defmacro with-animal [animal & body] 
    `(binding [speak (:sound ~animal)] 
     [email protected])) 
: गतिशील होने के लिए (जो rebinding की अनुमति देता है)

(defn :^dynamic speak [] (println "eh?")) 

एक बुनियादी टेम्पलेट मैक्रो बाध्य करने के लिए जानवर में समारोह से बात लिखने rebinding हो जाएगा 0

और यह परीक्षण:

(with-animal dog 
    (println (str "Dog: " (speak) "\n"))) 
Dog: wooooof             


और अब "उन्नत संस्करण" जो सिर्फ गुंजाइश गतिशील बंधन के लिए कोई ज़रूरत नहीं के साथ एक लेट का उपयोग करते हुए एक प्रतीक speak परिचय देता है।यह कहना नहीं है कि बाध्यकारी किसी भी तरह से खराब है, यह (let-binding [speak (fn [] "meow")] ...) लिखने की आपकी इच्छा को अधिक निकटता से फिट नहीं करता है इस प्रकार के मैको को एनाफोरिक कहा जाता है (यदि आप इस तरह के फैंसी नामों में हैं):

महत्वपूर्ण हिस्सा है ~' से पहले speak प्रतीक है कि स्पष्ट रूप से दायरे में एक गैर-योग्य प्रतीक का परिचय:

user> (defmacro with-animal [animal & body] 
    `(let [~'speak (:sound ~animal)] 
     [email protected])) 
#'user/with-animal 

user> (with-animal dog 
     (println (str "Dog: " (speak) "\n"))) 
Dog: wooooof 

nil 


मुझे आशा है कि इन दो उदाहरणों के बीच विरोधाभास एक गुंजाइश में एक वस्तु से व्यवहार बाध्यकारी के बारे में अपने सवाल का जवाब देने में कार्य करता है । पहला उदाहरण मैको के शरीर और उस शरीर से जिसे कुछ भी कहा जाता है, के लिए मूल्य को बांधता है। दूसरा उदाहरण केवल मैक्रो के शरीर के लिए नाम प्रस्तुत करता है।

+0

मुझे यह समाधान पसंद है। मैं खुद को एक ऐसा स्थान देख सकता हूं जो जानवरों के उपयोग के साथ सभी कार्यों को परिभाषित करता है, फिर प्रत्येक जानवर के लिए, उस फ़ाइल में इसे परिभाषित करता है। –

+1

'स्पीच' को किसी भी उदाहरण में फ़ंक्शन होने की आवश्यकता नहीं है, है ना? यह सिर्फ '(def ^: गतिशील बोल" एह? ") हो सकता है। आप जो भी कर रहे हैं वह किसी भी स्ट्रिंग में इसे संयोजित कर रहा है। – Ben

0

तुम सच में पशु प्रकार मुहावरे में बात करते हैं बनाना चाहते हैं, Clojure प्रोटोकॉल का उपयोग करें:

(defprotocol ISpeak 
    (speak [animal] "make the type say it's thing")) 

(deftype Dog [] 
    ISpeak 
    (speak [this] "Woof!")) 

(deftype Cat [] 
    ISpeak 
    (speak [_] "Meow!!")) ;;you can "drop" the item if not used using _ 

(def a-dog (Dog.)) 
(speak a-dog) 
;;=>"Woof!" 

(def a-cat (Cat.)) 
(speak a-cat) 
;;=>"Meow!!" 

कृपया ध्यान दें कि आप बोलते विधि के साथ किसी भी प्रकार (वर्ग) का विस्तार कर सकते हैं।

(extend java.util.Random 
    ISpeak 
    {:speak (fn [_] "I'm throwing dices at you!")}) 

(speak (java.util.Random.)) 
;;=>"I'm throwing dices at you!" 

वाक्य रचना जावा वर्गों के लिए थोड़ा अलग है, तो अधिक जानकारी के लिए Protocols documentation देखते हैं।

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