我正在尝试编写一个宏来构建类似于 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))))
任何帮助或指向更好的宏编写指南的指针都会很棒,谢谢。
最佳答案
让我们看看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))))
这不正是我们所追求的!首先,如果你想取消宏中的引用,你需要使用“`”(准引用/语法引用运算符),而不是“'”。另外,我不确定您对这些美元符号的追求是什么,但可能是您想要使用 clojure 的便捷快捷方式来使用 gensym
来保持卫生。但是,在每次使用它的标识符之后,您都需要立即使用它(因此 [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=>
关于macros - 从函数构建高阶函数的 Clojure 宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10986611/