2012-06-11 17 views
5

से उच्च ऑर्डर फ़ंक्शन बनाता है, मैं एक मैक्रो लिखने की कोशिश कर रहा हूं जो कि कंपोज़र में उपयोग किए गए मिडलवेयर बनाता है।क्लोजर मैक्रो जो एक फ़ंक्शन

मैं फोन करने के लिए सक्षम होना चाहते हैं:

(def-middleware plus-two [x] 
    (+ 2 x)) 

और परिणाम देखने के लिए की तरह है: अब तक ऑन लाइन गाइड पढ़ने से

(defn plus-two [f] 
(fn [x] 
    (f (+ 2 x))) 

मैं इस मिल गया है लेकिन यह पता काम नहीं कर रहा मेरे लिए:

(defmacro def-middleware [fn-name args & body] 
    '(defn ~fn-name [f] 
    (fn ~args 
     (f [email protected])))) 

कोई मदद या एक बेहतर मैक्रो लेखन गाइड करने के लिए एक सूचक धन्यवाद बहुत अच्छा होगा,।

+0

यह आपके लिए कैसे काम नहीं कर रहा है? –

+0

कंपाइलरएक्सप्शन java.lang.RuntimeException: def के लिए पहला तर्क एक प्रतीक होना चाहिए, संकलित करना: (NO_SOURCE_PATH: 33) – jdoig

+0

बैक-टिक का उपयोग करें, एकल कोट – Alex

उत्तर

8

देखते हैं क्या macroexpand-1 हमें देता है:

user=> (clojure.pprint/pprint (macroexpand-1 '(def-middleware plus-two [x] (+ 2 x)))) 
(defn 
~fn-name 
[f] 
$ 
(fn ~args$ (f (clojure.core/unquote-splicing body)))) 

नहीं ठीक है कि हम क्या करने के बाद हो! सबसे पहले चीज़ें: यदि आप मैक्रो में चीजों को अनवरोधित करना चाहते हैं, तो आपको "` "(quasiquote/syntax-quote ऑपरेटर) का उपयोग करने की आवश्यकता है, न कि" "। साथ ही, मुझे यकीन नहीं है कि आप उन डॉलर के संकेतों के बाद क्या कर रहे हैं, लेकिन हो सकता है कि आप स्वच्छता के लिए gensym का उपयोग करने के लिए क्लोजर के आसान शॉर्टकट के लिए जा रहे हैं। लेकिन आपको इसके द्वारा उपयोग किए जाने वाले प्रत्येक पहचानकर्ता के तुरंत बाद इसकी आवश्यकता है (इसलिए [f#], [f]$ नहीं), और आपको पहचानकर्ता की प्रत्येक घटना पर इसकी आवश्यकता है। और आप को args के साथ इसकी आवश्यकता नहीं है। इस सबको एक साथ रखें:

user=> (defmacro def-middleware [fn-name args & body] `(defn ~fn-name [f#] (fn ~args (f# [email protected])))) 
#'user/def-middleware 
user=> (clojure.pprint/pprint (macroexpand-1 '(def-middleware plus-two [x] (+ 2 x)))) 
(clojure.core/defn 
plus-two 
[f__594__auto__] 
(clojure.core/fn [x] (f__594__auto__ (+ 2 x)))) 
nil 
user=> 
+0

$ क्षमा करें जहां फॉर्म कॉपी और पेम से चिपका रहा है। और तुम सही हो # यह गायब था :) धन्यवाद। – jdoig

3

शायद यह सिर्फ एक मैक्रो व्यायाम है, लेकिन एक मिडलवेयर समारोह को परिभाषित करने की विशिष्ट उदाहरण अच्छा नहीं है - आप लचीलापन है कि मिडलवेयर अवधारणा आप देता है की एक बहुत कुछ खो देते हैं। उदाहरण के लिए, (+ 2 (f x)) के बजाय (f (+ 2 x)) का मूल्यांकन क्यों करना चाहिए? दोनों इस फ़ंक्शन को लपेटने के समझदार तरीके हैं, और आपका वाक्यविन्यास बाद वाले का वर्णन करने का कोई तरीका नहीं देता है। वास्तव में केवल फ़ंक्शन-रिटर्निंग-फ़ंक्शन को परिभाषित करना लचीला, सरल और आसान है; यह मैक्रो टेबल पर थोड़ा लाता है।

+0

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

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