解构形式和Compojure?

edo*_*lin 6 clojure destructuring compojure

我想我会发布这篇文章,因为我在没有真正了解正在发生的事情的情况下通过猜测来完成工作,我认为如果有人解释它可能会有所帮助.

我理解如何在Compojure处理程序中获取:params map的元素:

(GET "/something" [some_arg] "this is the response body")
Run Code Online (Sandbox Code Playgroud)

要么

(GET "/something" {{some_arg "some_arg"} :params} "this is the response body")
Run Code Online (Sandbox Code Playgroud)

虽然我不完全明白这{some_arg "some_arg"}部分在做什么:(

我也想访问:remote-addr请求的一部分以及some_arg.我结束了

(GET "/something" {{some_arg "some_arg"} :params ip :remote-addr}
    (do-something-with some_arg ip))
Run Code Online (Sandbox Code Playgroud)

所以,我得到了未加引号的字符串,some_arg并且ip是我想要绑定值的变量的名称,但上面的地图不是有效的Clojure映射.它是如何工作的?

我还得到这是根据Ring请求映射(由某种方式由defroutes宏提供)进行评估,但上面的表达式不是函数或宏定义,那么它如何在我的代码中"存在"为有效表达式?宏观参数的正常规则是否存在某种暂停?我一直无法找到这种非Lisp'er可理解的解构形式语法的定义.

Ray*_*yne 3

该映射是有效的解构映射。在任何绑定名称的地方,都可以使用解构。您可以在 a 中执行相同的操作let,如下所示:

user=> (let [{{some-arg "some_arg"} :params ip :remote-addr} {:remote-addr "127.0.0.1" :params {"some_arg" "some_value"}}] [ip some-arg])
["127.0.0.1" "some_value"]
Run Code Online (Sandbox Code Playgroud)

我写了一篇关于命名参数上下文中的映射解构的文章,但它适用于这里。您可能会发现这很有用:Clojure - 命名参数

很多博客文章演示了解构,包括这篇文章。我不确定哪一个是值得学习的规范地方。

我并不假装知道 compojure 到底对这张地图做了什么,但我认为它把它扔进了 let 或类似我上面演示的东西中。GET 是一个宏,因此它不必评估您传递给它的映射,这就是为什么除非它评估它,否则您不会收到错误。

user=> (defmacro blah [m])
#'user/blah
user=> (blah {a "b" c "d"})
nil
user=> (defn blah [m])
#'user/blah
user=> (blah {a "b" c "d"})
java.lang.Exception: Unable to resolve symbol: a in this context (NO_SOURCE_FILE:9)
Run Code Online (Sandbox Code Playgroud)

在幕后,魔法发生在该映射上,并被传递给一个名为解构的函数,该函数执行解构魔法。

除了正常的宏/特殊形式 foo 和延迟求值之外,这里实际上没有什么特别的事情发生。