有人可以使用 (assoc-in)
解释以下结果背后的原因吗? ?
(assoc-in {:foo {:bar {:baz "hello"}}} [:foo :bar] "world")
=> {:foo {:bar "world"}}
(assoc-in {:foo {:bar nil}} [:foo :bar :baz] "world")
=> {:foo {:bar {:baz "world"}}}
(assoc-in {:foo {:bar "hello"}} [:foo :bar :baz] "world")
=> ClassCastException java.lang.String cannot be cast to clojure.lang.Associative clojure.lang.RT.assoc (RT.java:702)
显然我可以替换 map 甚至
nil
使用另一种数据类型(例如字符串),但我不能用映射替换数据类型(例如字符串),因为它需要该数据类型已经是映射。人们将如何解决这个问题?我想实现以下目标:
(assoc-in {:foo {:bar "hello"}} [:foo :bar :baz] "world")
=> {:foo {:bar {:baz "world"}}}
最佳答案
assoc-in
在 assoc
之上实现.您可以替换 map 和nil
因为 assoc
对它们起作用:
(assoc {} :foo :bar) ;=> {:foo :bar}
(assoc nil :foo :bar) ;=> {:foo :bar}
但是
assoc
不适用于字符串:(assoc "string" :foo :bar) ;=> ClassCastException
顺便说一句,the definition的
assoc-in
很优雅:(defn assoc-in
;; metadata elided
[m [k & ks] v]
(if ks
(assoc m k (assoc-in (get m k) ks v))
(assoc m k v)))
如果您需要替换
assoc
的值不能被调用,您需要在更浅的一层上操作并替换整个 map 而不仅仅是值:(assoc-in {:foo {:bar "hello"}} [:foo :bar] {:baz "world"})
;=> {:foo {:bar {:baz "world"}}}
如果 map 中还有其他值您不想通过替换整个内容而丢失,您可以使用
update-in
与 assoc
:(update-in {:foo {:bar "hello"}} [:foo] assoc :baz "hi")
;=> {:foo {:bar "hello", :baz "hi"}}
关于Clojure:使用 assoc-in 的结果不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19692764/