1

我有一个关于两个功能的问题,一个是完整的地图,另一个是这样的特定关键字:

(def mapVal
 {:test "n"
  :anotherKey "n"})

(defn functionTest
 [& {:keys [test anotherKey] :or {:test "d" :anotherKey "d"}}]
 (println :test :anotherKey))

(defn mapFunc
 [map]
 (functionTest (get-in map [:test :anotherKey])))

目标是参数映射中的所有键都将正确传递给 functionTest。无论如何这可以工作吗?我尝试了一些东西,但我无法获取传递给 functionTest 的所有关键字和值。我不想要的只是地图的值,它应该通过关键字和值传递给另一个函数。

4

2 回答 2

2

你很接近。有几件事应该弄清楚。

首先,当您使用[& varname]该方法声明参数时,varname将是一个包含所有额外参数的列表。所以你不需要在这里使用那个' &'来解构输入。相反,您只需命名您希望成为变量的键。

尝试这个:

(defn functionTest
 [{:keys [test anotherKey]}]
 (println test anotherKey))

另一个问题是使用get-in. 随着get-in您使用该向量通过嵌套数据结构定义“路径”。例如,给定:

{:first {:a 1 :b 2} :second {:c 3 :d 4}}

您可以使用get-in以下方法获取值:second :c

(get-in {:first {:a 1 :b 2} :second {:c 3 :d 4}} [:second :c])

在您的情况下,您根本不需要使用get-in。你只需要通过整个地图。您定义的解构functionTest将处理其余部分。这是我所做的工作:

(defn mapFunc
 [map]
 (functionTest map))

我还建议您不要将该变量命名为 ' map',因为它与map函数冲突。

于 2016-05-28T04:22:22.963 回答
1

get-in用于访问嵌套的关联数据结构。

(def m {:a {:x 1}})
(get-in m [:a :x]) ;;=> 1

解构映射后,这些值在范围内并通过符号访问。您的示例应如下所示:

(def mapVal
  {:test "n"
  :anotherKey "n"})

(defn functionTest
  [& {:keys [test anotherKey]
      :or {:test "d" :anotherKey "d"}}]
  (println test anotherKey))

(defn mapFunc
  [m]
  (apply functionTest (apply concat (select-keys m [:test :anotherKey]))))


(mapFunc mapVal) ;;=> prints: n n

您必须完成此操作,因为functionTest它接受裸键值对作为可选参数(& 右侧的参数),如下所示:

(functionTest :test "n"
              :anotherKey "n" )
;;=> Also prints: n n

select-keys返回仅包含指定键的映射:

(select-keys mapVal [:test])
;; => {:test "n"}

应用于concat映射返回键和值的平面序列:

(apply concat (select-keys mapVal [:test :anotherKey]))
;; => (:test "n" :anotherKey "n")

apply将函数应用于 seq,就好像 seq 是它的参数列表:

(+ [1 2 3]) ;;=> Error.
(apply + [1 2 3]) ;; => 6

作为旁注,通常在 Clojure 代码中,对于大多数名称,蛇形大小写比骆驼大小写更受欢迎。

于 2016-05-28T04:42:29.760 回答