2012-10-29 10 views
6

try, एक दूसरे से एक है कि पहले से पुकारा जाता है में catch एक मैक्रो में है। काम करने के लिए निम्नलिखित कैसे प्राप्त करें?विभिन्न (लेकिन नेस्टेड) ​​मैक्रोज़ में कोशिश कर सकते हैं और पकड़ सकते हैं?

(defmacro catch-me [] 
    `(catch ~'Exception ~'ex 
    true)) 

(defmacro try-me [] 
    `(try (+ 4 3) 
     (catch-me))) 

विस्तार try-me अच्छा लग रहा है:

(clojure.walk/macroexpand-all '(try-me)) 

पैदावार

(try (clojure.core/+ 4 3) (catch Exception ex true)) 

लेकिन बुला (कोशिश-मुझे) पैदावार:

"Unable to resolve symbol: catch in this context", 

जो, Btw, भी है संदेश आपको आरपीएल में मिलेगा प्रयास में नहीं होने पर पकड़ का उपयोग करते समय।

अद्यतन:

यह मैं इसे कैसे काम करने के लिए (धन्यवाद, @Barmar) प्राप्त कर सकते है, यहाँ आप मेरी कोड के वास्तविक संदर्भ देख सकते हैं:

(defmacro try-me [& body] 
    `(try 
    [email protected] 
    [email protected](for [[e msg] [[com.mongodb.MongoException$Network "Database unreachable."] 
         [com.mongodb.MongoException "Database problem."] 
         [Exception "Unknown error."]]] 
     `(catch ~e ~'ex 
      (common/site-layout 
      [:div {:id "errormessage"} 
       [:p ~msg] 
       [:p "Error is: " ~e] 
       [:p "Message is " ~'ex]]))))) 

लेकिन यह मैं क्या था (एक अलग मैक्रो का उपयोग catch-me) के लिए उम्मीद:

(defmacro try-me [& body] 
    `(try 
    [email protected] 
    (catch-me com.mongodb.MongoException$Network "Database unreachable.") 
    (catch-me com.mongodb.MongoException "Database problem.") 
    (catch-me Exception "Unknown error."))) 

मुझे लगता है कि यह आसान हो लिखने/बनाए रखने के लिए होगा।

कोई भी विचार? मैं वाक्य रचना-के हवाले से की जरूरत है क्योंकि मैं पैरामीटर प्रदान करने कर रहा हूँ, यही कारण है कि दुर्भाग्य से आर्थर की जवाब लागू नहीं किया जा सकता है (कर सकते हैं किसी भी तरह या यह?) है, लेकिन मैं अभी तक मेरे वास्तविक संदर्भ पोस्ट नहीं किया था।

+0

मेरे वर्तमान अनुमान है कि (पकड़ने-मुझे) इससे पहले कि यह स्पष्ट हो कि यह एक कोशिश के अंदर है, पहले विस्तारित किया गया है। क्या यही है? उससे लड़ने के लिए कैसे? – 0dB

+1

मैक्रोज़ केवल उन स्थानों पर विस्तारित किए जाते हैं जहां एक अभिव्यक्ति का मूल्यांकन सामान्य रूप से किया जाएगा। 'पकड़' उप-अभिव्यक्ति अभिव्यक्ति नहीं होती है जिसका मूल्यांकन किया जाता है, वे 'try' के वाक्यविन्यास का हिस्सा हैं। – Barmar

+0

मैं वर्तमान में अभी भी इस प्रश्न को अनुत्तरित मानता हूं। यह परेशान है कि आर्थर का उदाहरण क्यों काम करता है लेकिन सिंटैक्स उद्धरण का उपयोग करने वाला कोई नहीं करता है, और, यह मैक्रोएक्सपैंड-सब एक काम कर रहे मैक्रो विस्तार को दिखाता है लेकिन इसके लिए एक सीधी कॉल एक त्रुटि के साथ विफल रहता है। कामकाज के लिए बाड़ार के लिए धन्यवाद। कोई अन्य विचार, कोई भी? – 0dB

उत्तर

5

कारण आपको लगता है कि त्रुटि है क्योंकि try के लिए वाक्यविन्यास है मिलती है:

(try expr* catch-clause* finally-clause?) 

इसका मतलब यह है पकड़ और अंत में खंड से पहले expr रूपों में से किसी संख्या में हो सकता है। try को स्कैन करता है expr रों जब तक यह एक है कि catch या finally साथ शुरू होता है पाता है। यह, इस किसी मैक्रो के विस्तार से पहले करता है के बाद से यह सिर्फ यह पता लगाने की जहां exprs और और पकड़/अंत में खंड शुरू कोशिश कर रहा है। यह सब catch और finally खंड एकत्र करता है और उनके लिए उपयुक्त त्रुटि हैंडलिंग वातावरण स्थापित करता है।

एक बार ऐसा करने के बाद, यह सामान्य रूप से सभी expr रूपों को निष्पादित करता है। तो यह उनके मैक्रोज़ का विस्तार करता है, और फिर उन्हें निष्पादित करता है। लेकिन catch, एक समारोह या विशेष रूप नहीं है यह सिर्फ कुछ है कि try शुरुआती चरण की नज़र रखता है। इसलिए जब इसे सामान्य रूप से निष्पादित किया जाता है, तो आपको उसी त्रुटि मिलती है जब आप इसे आरईपीएल में टाइप करते हैं।

क्या आप चाहिए शायद ऐसा कोई मैक्रो कि आप अपने पूरे कोड है कि try/catch अभिव्यक्ति है कि आप चाहते हैं में विस्तारित आसपास wrape बारे में है। जो कुछ आप पूरा करने की कोशिश कर रहे हैं उसके उदाहरण के बिना, एक विशिष्ट उत्तर देना मुश्किल है।

+0

मैं देख रहा हूं कि आप क्या कह रहे हैं, लेकिन यह महसूस हो रहा है कि 'कैच' से समस्या बहुत जल्द खत्म हो रही है और बहुत देर हो चुकी है, इस तरह मैंने आपका उत्तर पढ़ा है, क्या आप सहमत नहीं होंगे? यह भी समझाएगा कि @र्थुर का जवाब क्यों है (मैं उससे सहमत हूं कि यह सबसे सुंदर समाधान नहीं है) काम करता है: 'पकड़' को विभाजित किया गया है लेकिन अभी तक मूल्यांकन नहीं किया गया है। मैं ऐसा होने पर अभी भी काम कर रहा हूं और अभी भी सिंटैक्स-उद्धरण का उपयोग कर रहा हूं :-) मैंने आपके सुझाव पर अनुवर्ती किया है और मेरे सभी कोड को एक मैक्रो में लपेट लिया है, या तो इसे पोस्ट करेगा या, यदि मुझे लगता है, तो एक निर्णायक समाधान :-) – 0dB

+0

समस्या यह है कि 'पकड़' का कभी मूल्यांकन नहीं किया जाना चाहिए, "बहुत जल्द" नहीं है। 'पकड़' और 'आखिरकार' असली ऑपरेटर नहीं हैं, भले ही वे लिखे गए हों। 'Try' के शरीर को स्कैन करते समय संकलक उन्हें सचमुच देखता है। – Barmar

+0

ठीक है, लेकिन मुझे लगता है कि मैक्रो प्रोसेसिंग के दौरान, कोशिश केवल पहले 'चिपकाया' (उद्धृत) है, जो बताएगा कि @ आर्थर का समाधान क्यों काम करता है (भले ही मेरे लिए नहीं)? किसी भी मामले में, मुझे यह भ्रमित लगता है कि 'मैक्रोएक्सपैंड-ऑल' एक कामकाजी विस्तार दिखाता है लेकिन फिर भी यह काम नहीं करता है। – 0dB

1

संक्षिप्त उत्तर हाँ है, हालांकि विशेष रूपों के साथ घोंसले वाले मैक्रोज़ इस तरह के कुछ डबल-उद्धरण सिरदर्द का कारण बन सकते हैं।

user> (defmacro catch-me []         
      '(list 'catch 'Exception 'ex 
         'true)) 

user> (defmacro try-me [] 
    `(try (+ 4 3)    
        ~(catch-me))) 
#'user/try-me 

user> (try-me) 
7 

और देखने के लिए कि यह रूप में अच्छी तरह अपवाद पकड़ता:: यह विस्तार के दोनों स्तरों पर मूल्यांकन किया जा रहा से प्रतीकों को रोकने के लिए जरूरी है

user> (defmacro try-me [] 
    `(try (/ 4 0) 
       ~(catch-me))) 
#'user/try-me 
user> (try-me) 
true 
+0

आपके सुझाव और '(clojure.walk/macroexpand-all '(try-me) के बाद से)' दोनों काम मैं अभी भी एक को खोजने की कोशिश कर रहा हूं जो वाक्यविन्यास-उद्धरण का उपयोग करता है। यदि मैं इसे पाता हूं तो मैं पोस्ट करूंगा या बस @ बाड़मेर के सुझाव पर अनुवर्ती हूं। – 0dB

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