在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
)
不见得,也不会是个好主意。试想一下。
(let [{:all-the-keys} m]
(foo bar))
foo和bar是globals吗?是局部的吗?你应该从m中提取的键?如果m 有时 包含一个foo键,而foo也是一个全局函数? 有时你调用全局函数,有时你调用存储在m中的函数?
忽略技术上的问题(可以克服),这对可读性和可预测性来说真的是一场灾难。只要明确你要调出什么键就可以了,如果你经常要调出同样的十个键,你可以写一个简单的宏,如 (with-person p body)
这为你简化了那个常见的情况。
这个问题很老了,所以你可能已经忘记了,但它出现在google上,当我试图做同样的事情,所以如果我发布我的解决方案,它可能会帮助别人。
(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
绑定,同时执行一些评价-jitsu来确保这在运行时发生。
(def test-map {:cpp 88 :js 90})
(let-map test-map
(println js)
(println cpp))
;=> 90
;=> 88
你可以写一个宏来实现这一点(有效地创建一个迷你DSL),但我认为这不是一个好主意,原因如下。
我建议只用一个简单的 剂量q 在你的情况下,在地图上循环。
(let [my-map {:cpp 88 :js 90}]
(doseq [[k v] my-map]
(println v)))
注意: