2012-09-25 15 views
5

यह Treat Clojure macro as a function में चर्चा की गई समस्या के समान है, लेकिन शीर्ष उत्तर में दृष्टिकोण का प्रयास करते समय, मुझे एक त्रुटि मिली। मेरी विशिष्ट अनुप्रयोग के बारे में उम्मीद है कि बहुत अधिक जानकारी, आवश्यक नहीं है, क्योंकि यह काफी जटिल है, लेकिन यहाँ है कि मैं क्या करने की कोशिश की की एक आसुत संस्करण:मैक्रोज़ के लिए फ़ंक्शन/'आंशिक' के रूप में क्लोजर मैक्रो?

(defmacro make-fn [m arg1] 
    `(fn [& args#] 
     (eval `(~'~m ~'~arg1 [email protected]#)))) 

मैं इस संदर्भ में मैक्रो का प्रयोग किया:

(let [columns (make-columns table-width) 
     table-name (keyword (str "table_" n))] 
    (apply (make-fn helpers/tbl table-name) columns)) 

"हेल्पर्स/टीबीएल" एक मैक्रो है जो तालिका नाम कीवर्ड और कॉलम विनिर्देशों (जैसे [: वर्कर 100] या कुछ) वाली सूचियों की एक चर संख्या की अपेक्षा करता है। मैं कुछ परीक्षण की सुविधा के लिए फ्लाई पर यादृच्छिक डेटाबेस तालिका विनिर्देश बनाने की कोशिश कर रहा हूं।

CompilerException java.lang.RuntimeException: Unable to resolve symbol: table-name in this context, compiling:(NO_SOURCE_PATH:1) 

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

उत्तर

2

समस्या क्लोजर सिंटैक्स-कोट (बैकटिक) अभिव्यक्ति के भीतर प्रतीकों को हल करने के तरीके के कारण होती है। अनजाने परिवर्तनीय कैप्चर से बचने के लिए, क्लोजर हमेशा वर्क्स ( स्थानीय) के संदर्भ में सिंटैक्स-कोट अभिव्यक्ति के भीतर प्रतीकों का व्याख्या करता है।

आप सिंटैक्स-कोट द्वारा जेनरेट किए गए समकक्ष "अपने स्वयं के" फॉर्म-बिल्डिंग कोड को "रोलिंग" करके प्राप्त कर सकते हैं। यह पाप के रूप में के रूप में बदसूरत है, लेकिन यह काम करता है ... बस नहीं कहता मैं आपको चेतावनी देता नहीं किया:

(defmacro make-fn [m arg1] 
    (let [g (gensym)] 
    (list 'fn ['& g] 
     (list 'eval (list 'concat (list 'list m arg1) g))))) 

वाह, यह मेरी कॉमन लिस्प दिनों के लिए एक फ्लैशबैक की तरह है ...

+0

BTW , 'वाक्यविन्यास-उद्धरण' के बारे में दिलचस्प तथ्य: इसे पूरी तरह से पाठक में लागू किया गया है। जब पाठक बैकटिक देखता है, तो यह निम्न रूप को पढ़ता है, फिर इसे कोड में पुन: रूपांतरित करता है जो 'seq',' concat', और 'list' का उपयोग करता है। कंपाइलर केवल परिणामस्वरूप 'concat'/'list' कोड देखता है। –

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