Clojure中的宏,评估和引用

我试图编写一个宏,只在特定的环境中有条件地将compojure处理程序包装在中间件中。 我似乎在评估顺序中丢失了什么,应该怎样引用。 我目前的尝试如下:

(defn empty-middleware [handler]
  (fn [request] (handler request)))

(defmacro prod [handler middleware]
  (if (= "production" (System/getenv "APP_ENV"))
    (middleware handler)
    (empty-middleware handler)))

期望的用法是:

(in/prod (fn [handler]  (airbrake/wrap-airbrake handler config/airbrake-api-key)))

---编辑---

一些更多的信息:in / prod应该被用在内部线程宏中,这些线程包含许多中间件的路由,如:

(-> handler
    middleware1
    middleware2
    (in/prod (middleware3 middleware-3-param1))

中间件3和in / prod都需要处理程序作为参数。 在括号中包装中间件3时,不会将处理程序作为参数传递。 因此我认为需要一个宏。 我研究了如何制作/生成一个传递中间件3和中间件参数作为参数的函数:

(defn prod [handler middleware & middleware-params]
  (if (= "production" (System/getenv "APP_ENV"))
    (apply middleware handler middleware-params)
    handler))

它虽然改变了一点语法。 该调用看起来像:

(-> handler
    middleware1
    middleware2
    (in/prod middleware3 middleware-3-param1)

我将如何去使用像这样的语法:

(in/prod (middleware3 middleware-3-param1)

如果您希望应用的中间件也是宏,那么您可能需要将其作为宏,因此您正在遭受宏观传染。 在这种情况下,您只需要一个返回两个可能的s-expressins中的一个的宏来包含在生成的代码中。 其中一个处理程序直接被调用,另一个被包装在给定的中间件中。

(defmacro prod [handler middleware]
  (if (= "production" (System/getenv "APP_ENV"))
    `(~middleware ~handler) ;; or (list middleware handler)
     handler))

如果您目前没有受到宏观感染,而无法通过在其他地方删除宏来解决这个问题,那么您不需要使用这样的宏,并且您示例中的代码可以简单地用作函数而不是宏。 在任何情况下都不需要空中间件位。

链接地址: http://www.djcxy.com/p/65765.html

上一篇: Macros in Clojure, evaluation and quoting

下一篇: quoting choices based on ~ and ~@ in Clojure macro