5

compojureで使用されているものと同様のミドルウェアを構築するマクロを作成しようとしています。

電話をかけたい:

(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 ~@body))))

どんな助けやより良いマクロライティングガイドへのポインタも素晴らしいでしょう、ありがとう。

4

2 に答える 2

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))))

正確には私たちが求めているものではありません!まず最初に:マクロ内の引用符を解除する場合は、「'」ではなく「 `」(準引用符/構文引用符の演算子)を使用する必要があります。また、これらのドル記号で何を求めているのかはわかりませんがgensym衛生に使用するためのclojureの便利なショートカットを使用している可能性があります。ただし、使用する各識別子の直後に必要であり(つまり[f#]、ではなく[f]$)、識別子が出現するたびに必要になります。そして、あなたはそれを必要としませんargs。これらすべてをまとめると:

user=> (defmacro def-middleware [fn-name args & body] `(defn ~fn-name [f#] (fn ~args (f# ~@body))))
#'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=> 
于 2012-06-11T20:07:14.063 に答える
3

おそらくこれは単なるマクロ演習ですが、ミドルウェア関数を定義する特定の例は適切ではありません。ミドルウェアの概念がもたらす柔軟性の多くを失います。たとえば、なぜこれが(f (+ 2 x))代わりに評価する必要があるの(+ 2 (f x))ですか?どちらもこの関数をラップするための賢明な方法であり、構文では後者を説明する方法がありません。実際には、関数を返す関数を定義するだけで、柔軟性があり、シンプルで、簡単です。このマクロはテーブルにほとんど影響を与えません。

于 2012-06-12T04:16:52.767 に答える