【问题标题】:why are compojure routes defined as macros?为什么组合路由定义为宏?
【发布时间】:2017-11-24 19:44:20
【问题描述】:

例如 Luminus 网站states

Compojure 路由定义只是接受请求的函数 映射和返回响应映射...

(GET "/" [] "Show something")
...

但是复合路由不是函数

(defmacro GET "Generate a `GET` route."
  [path args & body]
  (compile-route :get path args body))

可以使用返回函数的函数make-route,但不允许解构。因此,作为一个函数,您不能使用 compojure 的特殊语法进行解构(即向量),但这会阻止任何形式的解构吗?宏是否给他们带来了性能提升?

(make-route :get "/some_path" some_handler)

不能使用宏包装器将破坏语法传递给函数吗?

【问题讨论】:

    标签: clojure compojure compojure-api


    【解决方案1】:

    使用宏的一个原因是用户可以编写函数和符号名称,而不必引用所有内容。以from the Clojure Cookbook为例:

    ; Routing
    (defroutes main-routes
      (GET "/"    [] (index))
      (GET "/en/" [] (index))
      (GET "/fr/" [] (index-fr))
      (GET "/:greeting/" [greeting] (view greeting)))
    

    如果GET 是一个函数,则必须引用所有index* 符号,加上viewgreeting

    ; Routing
    (defroutes main-routes
      (GET "/"    [] '(index))
      (GET "/en/" [] '(index))
      (GET "/fr/" [] '(index-fr))
      (GET "/:greeting/" '[greeting] '(view greeting)))
    

    由于函数参数在函数被调用之前被评估,(index) et al 将在表单被读取后立即被评估。此外,greeting arg 将在每个 HTTP 请求上发生变化,因此显然无法提前知道。

    宏还负责处理常规函数无法(通常)实现的所有解构魔法。

    经常令人困惑的事情(并且没有向初学者很好地解释)是这样的一行:

    (GET "/:greeting/" [greeting] (view greeting))
    

    不是正常的“Clojure 代码”。相反,GET 宏将摄取并用作如何生成“合法”Clojure 代码的一种简写形式(准确地说是域特定语言或 DSL)。 DSL 通常比最终生成的代码更短、更简单、更方便人类,就像 Clojure 比 Clojure 编译器生成的 Java 字节码或最终的机器汇编语言代码更短、更简单、更方便由 JVM 生成。

    简而言之,每个宏都是一个“预编译器”,它将 DSL 转换为普通的 Clojure,然后由 Clojure 编译器摄取以生成 Java 字节码。

    话虽如此,可以重新安排将所有宏魔法放入defroutes 宏中,这样GET 符号既不是函数也不是宏,而只是一种标记,如实现中的:get 关键字。作为用户,这些实现细节通常并不重要。

    更新

    最好只在函数不起作用或非常笨拙时使用宏。决定因素通常是是否要使用裸(未引用)符号,但不提前评估它们。 Core Clojure 本身为许多其他语言中的“内置”构造使用宏,包括defnforandorwhen 等。

    还要注意,宏不能做一些函数可以做的事情,例如作为filter等高阶函数的参数。

    总之,一个函数定义了一个行为。宏定义了语言扩展

    【讨论】:

    • 如果 GET 是一个函数,'(view greeting) 将毫无意义。你需要写一些更像(GET "/:greeting" (fn [req] (let-request [[greeting] req] (view greeting))))的东西,虽然很麻烦,但并非不可能。
    • 对于大多数功能,函数方法需要使用eval,这就是为什么宏解决方案是非常受欢迎的原因。
    • @AlanThompson - 纯粹出于好奇。我不是宏的忠实拥护者,因为我相信它们经常混淆真正发生的事情。当项目大量使用它们(设计决策等)时总是感兴趣。刚刚找到bidi - 数据结构方法在精神层面上对我说话。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-04
    • 2012-08-12
    • 1970-01-01
    • 2012-12-05
    • 2019-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多