2

我对 Clojure 非常陌生,通过阅读优秀的开源代码来学习 Clojure。所以我选择了 Ring 并开始阅读代码,但卡在了 assoc-query-params 函数中。(位于ring.middleware/params.clj

而且我不明白为什么要使用“合并”。谁能帮我理解这段代码片段?

(defn- assoc-query-params
  "Parse and assoc parameters from the query string with the request."
  [request encoding]

  ; I think (merge request (some-form)) is enough
  ; but the author used merge-with with merge function.

  (merge-with merge request
    (if-let [query-string (:query-string request)]
      (let [params (parse-params query-string encoding)]
        {:query-params params, :params params})
      {:query-params {}, :params {}})))
4

1 回答 1

4

这是函数的描述merge改写它表示如果多次遇到键,则将选择最新映射中的值。在您发布的示例中,这意味着 的值:query-params :params将按原样从函数的尾部获取,而不是将它们与请求中的内容相结合。

让我们看一下这个例子:

(def m {:a {:a-key1 "value1"} :b {:b-key1 "value3"} :c {}})
(def m2 {:a {:a-key2 "value2"} :b {}})

(merge m m2)
;-> {:a {:a-key2 "value2"}, :b {}, :c {}}

(merge-with merge m m2)
;-> {:a {:a-key1 "value1", :a-key2 "value2"}, :b {:b-key1 "value3"} :c {}}

因此,(merge-with merge ...)construct 为我们提供了一种在地图中合并地图的方法。您可以这样看:merge-with 将按键(:a :b :c在我们的示例中)对所有键/值对进行分组,并将合并应用于它们的值。

{:a (merge {:a-key1 "value1"} {:a-key2 "value2"}) 
 :b (merge {:b-key1 "value3"} {})
 :c (merge {})}

处理后我认为assoc-query-params作者的初衷是扩展:query-params:params不是完全替换它们。

于 2013-08-21T02:17:22.627 回答