Clojure:使用assoc-in的结果不一致 [英] Clojure: Inconsistent results using assoc-in

查看:92
本文介绍了Clojure:使用assoc-in的结果不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以使用(关联)解释以下结果的原因吗?

Can someone explain what's the reasoning behind the following results using (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)

显然,我可以用另一种数据类型(例如String)替换地图甚至 nil ,但是我不能替换数据类型(例如String)使用地图,因为它需要该数据类型已经是地图。

Apparently I can replace a map and even nil with another data type (e.g. String) but I can not replace a data type (e.g. String) with a map, because it need that data type to be already a map.

一个人将如何解决这个问题?我想实现以下目标:

And how would one work around this? I would like to achieve the following:

(assoc-in {:foo {:bar "hello"}} [:foo :bar :baz] "world")
=> {:foo {:bar {:baz "world"}}}


推荐答案

assoc-in 已实现在 assoc 之上。您可以替换地图和 nil ,因为 assoc 可以处理它们:

assoc-in is implemented on top of assoc. You can replace maps and nil because assoc works on them:

(assoc {} :foo :bar)  ;=> {:foo :bar}
(assoc nil :foo :bar) ;=> {:foo :bar}

但是 assoc 不适用于字符串:

(assoc "string" :foo :bar) ;=> ClassCastException

顺便说一句, 关联的定义非常优美:

As an aside, the definition of assoc-in is quite graceful:

(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 的值,则需要改用更浅的层次并替换整个地图,而不只是值:

If you need to replace a value that assoc can't be called on you need to instead act on one level shallower and replace the whole map rather than just the value:

(assoc-in {:foo {:bar "hello"}} [:foo :bar] {:baz "world"})
;=> {:foo {:bar {:baz "world"}}}

如果其中包含其他值不想替换整个地图而丢失的地图,可以使用 update -in assoc

If there are other values within the map that you don't want to lose by replacing the whole thing, you can use update-in with assoc:

(update-in {:foo {:bar "hello"}} [:foo] assoc :baz "hi")
;=> {:foo {:bar "hello", :baz "hi"}}

这篇关于Clojure:使用assoc-in的结果不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆