在核心命名空间的compojure库中,我看到以下形式:
(defn- compile-route
"Compile a route in the form (method path & body) into a function."
[method route bindings body]
`(#'if-method ~method
(#'if-route ~(prepare-route route)
(fn [request#]
(let-request [~bindings request#]
(render (do ~@body) request#))))))
Run Code Online (Sandbox Code Playgroud)
和
(defmacro GET "Generate a GET route."
[path args & body]
(compile-route :get path args body))
Run Code Online (Sandbox Code Playgroud)
进一步在文件中,if-method和if-route函数用defn-s 定义.
我不明白#'这个compile-route功能的含义.文档(var ...)说:
符号必须解析为var,并返回Var对象本身(而不是其值).读者宏#'x扩展为(var x).
但对我而言,在正在发生的事情的背景下(即从defmacro调用),它只是意味着它将返回符号的价值,这与可替代性听起来是一样的:
(def x 5)
(+ x 7)
-> 12
Run Code Online (Sandbox Code Playgroud)
即(+ x 7)扩展到或相同,(+ 5 7)
我在这里错过了什么?
if-method看了一段时间后,我开始怀疑它与和if-route函数实际上是私有的( )有关(defn- if-route ...)。
另外,对于宏,当您使用反引号(“`”)时,您实际上在最终扩展中获得了完全命名空间指定的符号:
`(+ 2 3)
Run Code Online (Sandbox Code Playgroud)
将扩展到
(clojure.core/+ 2 3)
Run Code Online (Sandbox Code Playgroud)
由于这些方法是私有的,因此在正常扩展中无法访问它们,因此使用 var 函数来获取保存对此时必须在扩展中调用的实际函数的引用的符号。