在clojure中,可以像这样解构地图的某些键:
(let [{:keys [cpp js]} {:cpp 88 :js 90}]
(println js); 90
(println cpp); 88
)
有没有办法解构所有地图的键?
可能是这样的:
(let [{:all-the-keys} {:cpp 88 :js 90}]
(println js); 90
(println cpp); 88
)
答案 0 :(得分:23)
不是真的,这不是一个好主意。想象:
(let [{:all-the-keys} m]
(foo bar))
foo和bar全局?当地人?你应该从m中提取的密钥?如果m 有时包含foo键,那么这段代码应该怎么办?foo也是一个全局函数?有时你调用全局,有时你调用存储在m?
中的函数忽略技术问题(其中大部分可能都可以克服),这对可读性和可预测性来说确实是一场灾难。只要明确你想要拔出什么钥匙;如果您经常想要提取相同的十个密钥,您可以编写一个简单的宏,如(with-person p body)
,它可以简化您的常见情况。
答案 1 :(得分:9)
这个问题很老了所以你可能已经忘记了它,但是当我尝试做同样的事情时它出现在谷歌上,所以如果我发布我的解决方案,它可能会帮助其他人。
(defmacro let-map [vars & forms]
`(eval (list 'let (->> ~vars keys
(map (fn [sym#] [(-> sym# name symbol) (~vars sym#)]))
(apply concat) vec)
'~(conj forms 'do))))
这基本上将地图{:cpp 88 :js 90}
转换为绑定形式[cpp 88 js 90]
,然后构造let
绑定,同时执行一些eval-jitsu以确保在运行时发生这种情况。 / p>
(def test-map {:cpp 88 :js 90})
(let-map test-map
(println js)
(println cpp))
;=> 90
;=> 88
答案 2 :(得分:6)
你可以写一个宏来做这件事(有效地创建一个迷你DSL),但我认为这不是一个好主意,原因如下:
我建议您在案例中使用简单的doseq来遍历地图:
(let [my-map {:cpp 88 :js 90}]
(doseq [[k v] my-map]
(println v)))
请注意: