题
我以为我会发布这个问题,因为我可以通过猜测工作,而没有真正了解发生的事情,我认为如果有人解释了它可能会有所帮助。
我了解如何在Compojure处理程序中获取:参数映射的元素:
(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_arg
和 ip
是我想要绑定的变量的名称,但上面的映射不是有效的clojure映射。它是如何工作的?
我还知道这是针对戒指请求图评估的(这是由 defroutes
宏)但是上面的表达不是函数或宏定义,因此它如何作为我代码中的有效表达式“存在”?是否有某种暂停宏观论据的规则?我无法找到对这种非lisp'er可以理解的破坏形式语法的定义。
解决方案
该地图是有效的破坏地图。在您绑定名称的任何地方,都可以使用破坏性。你可以在 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"]
我写了一篇有关在命名参数的上下文中破坏地图的文章,但此处适用。您可能会发现这有用: clojure-命名参数
有 很多 展示破坏性的博客文章,包括 这 一。我不确定哪一个是一个可以学习的规范场所。
我不假装知道综合纸在引擎盖下的地图上的作用,但是我认为它会像我上面所展示的那样将其扔进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)
在引擎盖下,魔术发生在那张地图上,并传递给一种破坏性魔术的功能。
除了普通的宏观/特殊表格FOO和延迟评估外,这里没有什么特别的事情。
其他提示
破坏性发生在绑定形式中,对于破坏所绑定的VAR的地图,左侧是左侧,钥匙在右侧:
user=> (let [{a :foo} {:foo :bar}] user=* a) :bar
Compojure正在幕后做一个绑定形式,因此您在上面使用的地图破坏形式有效地变成了类似的东西:
(let [{{some_arg "some_arg"} :params} request] ...)
在哪里 request
是隐式提供的地图。
向量版本(例如 [some_arg]
),是仅绑定的替代方案 :params
请求中包含的地图。