Clojure:如何传递两组无界参数?

时间:2010-02-18 17:09:39

标签: clojure

举例说明:

(def nest1 {:a {:b {:c "foo"}}})
(def nest2 {:d {:e "bar"}})

如果我想在任意级别上联合这些巢,我可以明确地这样做:

(conj (-> nest1 :a :b) (-> nest2 :d)) ; yields {:e "bar", :c "foo"}

(conj (-> nest1 :a) (-> nest2 :d)) ; yields {:e "bar", :b {:c "foo"}}

但是如果我想创建一个接受nest1和nest2的“深度”作为参数的函数呢?

; Does not work, but shows what I am trying to do
(defn join-nests-by-paths [nest1-path nest2-path]
   (conj (-> nest1 nest1-path) (-> nest2 nest2-path))

我可能会试着这样称呼它:

; Does not work
(join-nests-by-paths '(:a :b) '(:d))

这不起作用。我不能简单地将每个“路径”作为列表传递给函数(或者我可以,但需要在函数中以不同方式使用它)。

有什么想法? TIA ... 肖恩

1 个答案:

答案 0 :(得分:5)

使用get-in

(defn join-by-paths [path1 path2]
  (conj (get-in nest1 path1) (get-in nest2 path2)))

user> (join-by-paths [:a :b] [:d])
{:e "bar", :c "foo"}
user> (join-by-paths [:a] [:d])
{:e "bar", :b {:c "foo"}}

您的版本实际上是这样做的:

user> (macroexpand '(-> nest1 (:a :b)))
(:a nest1 :b)
如你所说,

不起作用。

get-in有朋友assoc-inupdate-in,全部用于处理嵌套的地图地图。在clojure.conrtrib中有一个dissoc-in

(在Clojure中,当您传递连续的事物组时,使用向量而不是引用列表更为惯用。)