2012-10-01 19 views
14

में नेस्टेड वाक्य रचना-उद्धरण में समन्वय ऑटो gensym Clojure में, आप gensym उपयोग करने के लिए अपने मैक्रो में आंतरिक उपयोग के लिए उन्हें स्वच्छ रखने के लिए के लिए प्रतीक बनाने की जरूरत है। हालांकि, कभी-कभी आपको नेस्टेड सिंटैक्स-कोट्स में एक ही प्रतीक का उपयोग करने की आवश्यकता होती है। उदाहरण के लिए, अगर मैं let के साथ एक प्रतीक करने के लिए एक मूल्य के लिए बाध्य और यह एक unrolled पाश में तीन बार प्रिंट करना चाहते हैं, मैंClojure

`(let [x# 1] 
    [email protected](repeat 3 
      `(println x#))) 

करना चाहते हैं लेकिन उस का उत्पादन करेगा

(clojure.core/let [x__2__auto__ 1] 
        (clojure.core/println x__1__auto__) 
        (clojure.core/println x__1__auto__) 
        (clojure.core/println x__1__auto__)) 

x# एक उत्पन्न करता है फॉर्म में println के मुकाबले अलग-अलग प्रतीक हैं - क्योंकि वे विभिन्न वाक्यविन्यास-उद्धरणों से बनाए गए थे।

इसे हल करने के लिए, मैं पहले से प्रतीक पैदा करते हैं और वाक्य रचना-उद्धरण के लिए यह इंजेक्षन कर सकते हैं:

(clojure.core/let [G__7 1] 
        (clojure.core/println G__7) 
        (clojure.core/println G__7) 
        (clojure.core/println G__7)) 
:

(let [x (gensym)] 
    `(let [~x 1] 
    [email protected](repeat 3 
       `(println ~x))) 
) 

यह एक ही प्रतीक हर जगह की जरूरत के साथ सही परिणाम का उत्पादन करेगा,

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

तो, वहाँ किसी भी तरह से नेस्टेड वाक्य रचना-उद्धरण के साथ ऑटो gensym का उपयोग करें और उन्हें एक ही प्रतीक का उत्पादन करने के लिए है?

उत्तर

11

ऑटो gensym'd प्रतीकों वाक्य रचना-उद्धरण है कि उन्हें परिभाषित करता है के भीतर ही मान्य होते हैं और वे गैर उद्धृत कोड में काम नहीं करते क्योंकि उस वाक्य रचना बोली का हिस्सा नहीं है।

यहाँ प्रतीक x# यह द्वारा बदल दिया जाता है, क्योंकि यह वाक्य रचना बोली के दायरे के भीतर है gensym है:

core> `(let [x# 1] x#) 
(clojure.core/let [x__1942__auto__ 1] x__1942__auto__) 

और यदि आप इसे गंदें शब्द बोलना यह अब अनुवाद हो जाता है यह है में वाक्य रचना बोली:

core> `(let [x# 1] [email protected]#) 
CompilerException java.lang.RuntimeException: Unable to resolve symbol: x# in this context, compiling:(NO_SOURCE_PATH:1) 

ऑटो gensyms, वाक्य रचना-उद्धरण के भीतर एक बहुत ही सुविधाजनक शॉर्टकट हैं अन्य सभी स्थानों आप जाहिरा तौर पर सीधे gensym उपयोग करने के लिए के रूप में अपने बाद में उदाहरण के साथ मामला है की जरूरत है।

इस मैक्रो को ढूढ़ने के अन्य तरीके हैं, इसलिए ऑटोगोनिन्सम काम करेंगे हालांकि क्लोजर और अन्य लिप्स में मैक्रो के शीर्ष पर एक लेटेस्टेड प्रतीकों को घोषित करना बहुत सामान्य है।

+0

धन्यवाद। मैं काम करने के लिए प्रिंट अभिव्यक्ति को सामान्य उद्धृत नहीं कर सकता, लेकिन मुझे लगता है कि यह किसी भी जटिल मैक्रोज़ के लिए बोझिल हो जाएगा ... –

+0

यदि आप ऐसा कुछ करते हैं, तो मैं दृढ़ता से \ 'println, नहीं 'println का उपयोग करने की सलाह देता हूं - मैक्रो उपयोगकर्ता के असामान्य नामस्थान या शब्दावली संदर्भ के मामले में पूर्व नाम-कैप्चर के अधीन नहीं है। – amalloy

+0

अच्छा बिंदु! मैं उस –

8

आपका विधि (बुला gensym) सही एक है।

हालांकि कुछ मामलों में आप doto, -> या ->> के चालाक उपयोग के साथ प्राप्त कर सकते हैं। देखें:

`(let [x# 1] 
    (doto x# 
    [email protected](repeat 3 `println))) 
+0

में वास्तव में सही संपादन किया गया था, मैंने वास्तव में 'doto' का उपयोग करने के बारे में सोचा था, लेकिन कमांड खोजने में विफल रहा - मैं देख रहा था 'डॉविथ' की तर्ज पर कुछ के लिए, क्योंकि यही मैं अन्य भाषाओं से उपयोग करता हूं ... –