因为我见过到目前为止,Clojure的核心功能几乎都是针对不同类型的集合,例如工作conj,first,rest等我有点疑惑,为什么disj和dissoc是不同的,虽然; 他们有完全相同的签名:
(dissoc map) (dissoc map key) (dissoc map key & ks)
(disj set) (disj set key) (disj set key & ks)
Run Code Online (Sandbox Code Playgroud)
和相当类似的语义.为什么这些都不是由同一个功能覆盖?我能看到的唯一一个支持这一点的论点是,map既有(assoc map key val)并且都有(conj map [key val])添加条目,而set只支持(conj set k).
我可以编写一个单行函数来处理这种情况,但是Clojure在很多时候都是如此优雅,以至于每当它不是:)时它真的很刺激我
只是为Arthur的答案提供一个平衡点:conj甚至更早定义(名称conj出现在core.clj的第82行vs.1443 for disj和1429 for dissoc),但适用于所有Clojure集合类型.:-)显然它不使用协议 - 而是使用常规Java接口,就像大多数Clojure函数一样(事实上我相信当前Clojure中使用协议的唯一"核心"功能是reduce/ reduce-kv).
我猜想这是由于一种美学选择,并且确实可能与地图支持的方式有关conj- 他们是否支持disj,人们可能期望它采用可传递给的相同论点conj,这将是有问题的:
;; hypothetical disj on map
(disj {:foo 1
[:foo 1] 2
{:foo 1 [:foo 1] 2} 3}
}
{:foo 1 [:foo 1] 2} ;; [:foo 1] similarly problematic
)
Run Code Online (Sandbox Code Playgroud)
应该返回{},{:foo 1 [:foo 1] 2}还是{{:foo 1 [:foo 1] 2} 3}?conj愉快地接受[:foo 1]或{:foo 1 [:foo 1] 2}作为conj地图的东西.(conj有两个map参数的意思merge;确实merge是实现的conj,加上特殊处理nil).
因此,dissoc对地图来说也许是有道理的,因此它很明显它会删除一个键而不是"可能是某些东西conj".
现在,理论上dissoc可以在集合上工作,但也许人们可能会期望它们也支持assoc,这可能没有用.值得指出的是,向量确实支持assoc而不是dissoc,所以这些并不总是在一起; 这里肯定存在一些审美紧张.