2011-10-04 16 views
5

में एक namespace योग्य समारोह नाम बनाओ मैं कार्यों कि करने के लिए और कुछ कोड को बाह्य सिस्टम द्वारा परिभाषित से नक्शा का एक समूह है:एक मैक्रो

(defn translate-from-ib-size-tick-field-code [val] 
    (condp = val 
    0 :bid-size 
    3 :ask-size 
    5 :last-size 
    8 :volume)) 

(defn translate-to-ib-size-tick-field-code [val] 
    (condp = val 
    :bid-size 0 
    :ask-size 3 
    :last-size 5 
    :volume 8)) 

मैं दोहराव को दूर करने के लिए मैक्रो करना चाहते हैं :

#_ (translation-table size-tick-field-code 
         {:bid-size 0 
         :ask-size 3 
         :last-size 5 
         :volume 8})  

मैं इस तरह मैक्रो शुरू कर दिया:

(defmacro translation-table [name & vals] 
    `(defn ~(symbol (str "translate-to-ib-" name)) [val#] 
    (get [email protected] val#))) 

जिसके परिणामस्वरूप समारोह शरीर सही लगता है, लेकिन समारोह का नाम गलत है:

re-actor.conversions> (macroexpand `(translation-table monkey {:a 1 :b 2})) 
(def translate-to-ib-re-actor.conversions/monkey 
    (.withMeta (clojure.core/fn translate-to-ib-re-actor.conversions/monkey  
    ([val__10589__auto__] 
     (clojure.core/get {:a 1, :b 2} val__10589__auto__))) (.meta ... 

मैं चाहूँगा "का अनुवाद करने के लिए ib-", नाम स्थान के लिए एक उपसर्ग के बजाय, समारोह नाम के हिस्से के रूप में प्रदर्शित करने के रूप में यह पता चला।

मैं क्लोजर मैक्रोज़ के साथ ऐसा कैसे कर सकता हूं? अगर मैं इसे गलत कर रहा हूं और किसी कारण से मैक्रोज़ का उपयोग नहीं करना चाहिए, तो कृपया मुझे बताएं, लेकिन मैं यह जानना चाहूंगा कि इस तरह के फ़ंक्शन नाम कैसे बनाएं ताकि सामान्य रूप से क्लोजर और मैक्रोज़ की मेरी समझ में सुधार हो सके। । धन्यवाद!

उत्तर

7

मैक्रो मुद्दा दोहरा है:

`(translation-table monkey {:a 1 :b 2}) 
=> (foo.bar/translation-table foo.bar/monkey {:a 1, :b 2}) 

जहां foo.bar जो कुछ भी नाम स्थान है:

1) आप एक बैकटिक जब प्रपत्र macroexpand को पारित कर दिया है, जो भीतर प्रतीकों नाम स्थान-उत्तीर्ण हवाले से उपयोग कर रहे हैं आप अंदर हैं

2) आप defn आइटम का नाम name का उपयोग कर बना रहे हैं, जो नामस्थान-योग्य होने पर, "foo.bar/monkey" को स्ट्रिंग करेगा।

(defmacro translation-table [tname & vals] 
    `(defn ~(symbol (str "translate-to-ib-" (name tname))) [val#] 
    (get [email protected] val#))) 

सूचना है कि हम नाम स्थान हिस्सा बिना tname के नाम हो रही है, name फ़ंक्शन का उपयोग: यहाँ एक संस्करण है कि काम करता रहेगा।

एक मैक्रो सही समाधान यहाँ है कि क्या बात है, नक्शे शायद नहीं :-) इस तरह एक साधारण मामले के लिए, मैं सिर्फ इस्तेमाल कर सकते हैं:

(def translate-from-ib-size-tick-field-code 
    {0 :bid-size 
    3 :ask-size 
    5 :last-size 
    8 :volume}) 

;; swap keys & vals 
(def translate-to-ib-size-tick-field-code 
    (zipmap (vals translate-from-ib-size-tick-field-code) 
      (keys translate-from-ib-size-tick-field-code))) 

(translate-from-ib-size-tick-field-code 0) 
=> :bid-size 

(translate-to-ib-size-tick-field-code :bid-size) 
=> 0 

गति का ही महत्व है, तो बाहर case जाँच ।

+0

धन्यवाद, यह वही है जो मैं दोनों बिंदुओं पर देख रहा था। –

3

एक अलग बिंदु पर कुछ अनचाहे सलाह: (get [email protected] val#) बेहद संदिग्ध है। आपके मैक्रो ने कई तर्क लेने का आरोप लगाया है, लेकिन यदि यह दो से अधिक हो जाता है तो यह केवल कुछ ऐसा करेगा जो कोई समझ नहीं लेता है। उदाहरण के लिए,

(translation-table metric {:feet :meters} 
          {:miles :kilometers} 
          {:pounds :kilograms}) 
एक तरफ एक भयानक अनुवाद तालिका होने से

, कोड है कि हमेशा एक अपवाद फेंकता के लिए विस्तारित:

(defn translate-to-ib-metric [val] 
    (get {:feet :meters} 
     {:miles :kilometers} 
     {:pounds :kilograms} 
     val))) 

get है कि कई तर्क, निश्चित रूप से नहीं ले करता है, और यह वास्तव में क्या नहीं है आप वैसे भी मतलब था।सबसे सरल ठीक हो केवल दो तर्क की अनुमति के लिए होगा:

(defmacro translation-table [name vals] 
    (... (get ~vals val#))) 

लेकिन ध्यान दें मतलब यह है कि यह मान नक्शा हर बार समारोह में कहा जाता है का पुनर्निर्माण हो जाता है - समस्याग्रस्त अगर यह गणना करने के लिए महंगा है, या साइड इफेक्ट है। तो अगर मैं इसे मैक्रो के रूप में लिख रहा था (हालांकि जस्टिन का जवाब देखें - आप क्यों करेंगे?), मैं इसे इस प्रकार करूँगा:

(defmacro translation-table [name vals] 
    `(let [vals# ~vals] 
    (defn ~(symbol (str "translate-to-ib-" name)) [val#] 
     (get vals# val#)))) 
+0

धन्यवाद! मैं वहां "&" डालने का मतलब नहीं था और जब तक मैंने आपकी टिप्पणी नहीं देखी, तब तक मेरे लिए एक समस्या उत्पन्न हुई। –