2011-10-13 15 views
21

मैं एक छोटे से Clojure मैक्रो है कि एक प्रकार संकेत के साथ def सा स्ट्रिंग बनाने के लिए कोशिश कर रहा हूँ:Clojure defmacro खो देता है मेटाडाटा

(defmacro def-string [name value] 
    `(def ^String ~name ~value)) 

(def-string db-host-option "db-host") 

जब मैंने इसे macroexpand, प्रकार संकेत खो दिया है:

(macroexpand '(def-string db-host-option "db-host")) 
;=> (def db-host-option "db-host") 

इसे संकेत देने के प्रकार के ज्ञान को कभी भी ध्यान न दें।

मेट्रो मेटाडेटा क्यों खो रहा है? मैं इस मैक्रो, या किसी भी मेटाडेटा को कैसे लिखूं?

उत्तर

32

^ एक पाठक मैक्रो है। defmacro इसे कभी नहीं देख पाता है। संकेत (unquote name) सूची में रखा गया है। प्रभाव देखने के लिए उदाहरण के लिए (meta ^String 'x)(meta ' ^String x) के साथ तुलना करें।

आपको प्रतीक पर संकेत डालना होगा।

(defmacro def-string 
    [name value] 
    `(def ~(vary-meta name assoc :tag `String) ~value)) 

और उपयोग:

user=> (def-string foo "bar") 
#'user/foo 
user=> (meta #'foo) 
{:ns #<Namespace user>, :name foo, :file "NO_SOURCE_PATH", :line 5, :tag java.lang.String} 
+1

आह की तरह कुछ! बेशक, पाठक मैक्रोज़ defmacros से पहले मूल्यांकन किया जाता है। धन्यवाद। – Ralph

5

मेटाडाटा एक macroexpand में दिखाई नहीं है, क्योंकि यह "अदृश्य" माना जाता है करता है।

यदि मैक्रो सही है (जो यह नहीं है) तो आप var पर मेटा डेटा का निरीक्षण करने के लिए कॉल (मेटा # 'डीबी-होस्ट-ऑप्शन) कॉल करने में सक्षम होना चाहिए।

ध्यान दें कि (डीफ़ sym ...) प्रतीक से प्राप्त होने वाले var पर मेटाडेटा डालता है। लेकिन^टैग ~ नाम मेटा डेटा को ~ नाम (अनकोट नाम) पर सेट करता है, न कि पारित प्रतीक पर नाम के लिए। यह^टैग के बाद से कुछ और नहीं कर सकता ... पाठक द्वारा प्रसंस्करण किया जाता है, जो मैक्रो विस्तार शुरू होने के बाद ही समाप्त हो चुका है।

आप चाहते

(defmacro def-string [name value] 
    `(def ~(with-meta name {:tag String}) ~value)) 


user> (def-string bar 1) 
#'user/bar 
user> (meta #'bar) 
{:ns #<Namespace user>, :name bar, :file "NO_SOURCE_FILE", :line 1, :tag java.lang.String} 
संबंधित मुद्दे