clojure - 解构形式和组合?

标签 clojure compojure destructuring

我想我会发布这个,因为我通过猜测来工作,而没有真正了解发生了什么,我认为如果有人解释它可能会有所帮助。

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

(GET "/something" [some_arg] "this is the response body")

或者
(GET "/something" {{some_arg "some_arg"} :params} "this is the response body")

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

我还想访问 :remote-addr请求的一部分以及 some_arg .最后我得到了
(GET "/something" {{some_arg "some_arg"} :params ip :remote-addr}
    (do-something-with some_arg ip))

所以,我得到了未加引号的字符串 some_argip是我希望将值绑定(bind)到的变量的名称,但上面的映射不是有效的 Clojure 映射。它是如何工作的?

我还知道这是针对 Ring 请求映射(由 defroutes 宏提供的)评估的,但上面的表达式不是函数或宏定义,所以它如何“存在”为我的代码中的有效表达式?宏参数的正常规则是否有某种暂停?我一直无法找到这个非 Lisp'er 可以理解的解构形式的语法定义。

最佳答案

该映射是一个有效的解构映射。在绑定(bind)名称的任何地方,都可以使用解构。你可以在 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"]

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

有很多博客文章展示了解构,包括 this一。我不确定哪一个会是一个典型的学习场所。

我不会假装知道 compojure 到底对引擎盖下的那张 map 做了什么,但我认为它会将它扔进一个 let 或类似的东西中,就像我上面演示的那样。 GET 是一个宏,因此它不必评估您传递给它的 map ,这就是为什么除非它评估它,否则您不会收到错误。
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)

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

除了正常的宏/特殊形式 foo 和延迟评估之外,这里并没有什么特别之处。

关于clojure - 解构形式和组合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4089162/

相关文章:

emacs - Clojure Hello World - "No such namespace"错误

clojure - 如何简化 Compojure 路线?

javascript - 直接导入 ES6 模块元素还是在导入后解构 const 赋值?

java - 如何找到运行 Compojure 的网络托管服务

clojure - compojure/clojure GET 路由与 CSS 给出纯文本样式表响应

TypeScript 解构了带有类型或接口(interface)的默认参数

javascript - 创建对象时,如果值未定义,则不包含在新对象中

clojure - 在 clojure 的循环中改变数据是否可以?

clojure - 如何在 Clojure 中创建可调用对象?

clojure - 为什么是 :else not (else) in clojure?