2012-06-11 2 views
5

저는 compojure와 비슷한 미들웨어를 작성하는 매크로를 작성하려고합니다.함수에서 고차 함수를 생성하는 Clojure 매크로

내가 전화를 할 수 있도록하려면 :

(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

CompilerException java.lang.RuntimeException : def에 대한 첫 번째 인수는 Symbol이어야하며 다음과 같이 컴파일해야합니다. (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)))) 

아니 정확하게 우리가 계신! 가장 먼저해야 할 일 : 매크로에서 인용 부호를 인용 부호로 묶으려면 " '"가 아닌 "`"(quasi quote/syntax-quote 연산자)를 사용해야합니다. 또한, 당신이 그 달러 기호들로 무엇을하고 있는지 확신 할 수 없지만, 일 수 있습니다. 위생을 위해 gensym을 사용하기위한 clojure의 편리한 바로 가기가 될 것이라는 점에 유의하십시오. 그러나 사용하는 각 식별자 (즉, [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

Vim에서 $ where where copy and paste. 죄송합니다. 그리고 당신 말이 맞아요. 실종 된 #입니다. :) 고마워요. – jdoig

3

것은 아마도 이것은 단지 매크로 운동이지만, 미들웨어 기능을 정의하는 구체적인 예는 좋지 않다. 예를 들어 (+ 2 (f x)) 대신 (f (+ 2 x))을 평가해야하는 이유는 무엇입니까? 두 함수 모두이 함수를 감싸는 합리적인 방법이며 구문은 후자를 설명 할 방법이 없습니다. 실제로 함수를 반환하는 함수를 정의하는 것은 유연하고 간단하며 쉽습니다. 이 매크로는 테이블에 거의 영향을주지 않습니다.

+0

감사합니다. amalloy; 저는 매크로를 배우는 디딤돌으로 사용하고 있으며, 뭔가를 감싸는이 큰 멍청한 건물에 반대하는보다 구체적인 미들웨어와 같은 기능을 구축합니다 ... 당신이 옳다면, 현재 서 있습니다. 단락 등을 할 수 없으며 물건을 포장하는 방법을 설명 할 수 없습니다. – jdoig

관련 문제