gpt4 book ai didi

clojure - 为什么 `disj` 和 `dissoc` 在 Clojure 中有不同的功能?

转载 作者:行者123 更新时间:2023-12-03 18:23:52 26 4
gpt4 key购买 nike

据我所知,Clojure 的核心功能几乎总是适用于不同类型的集合,例如conj , first , rest等。我有点疑惑为什么disjdissoc虽然不同;它们具有完全相同的签名:

(dissoc map) (dissoc map key) (dissoc map key & ks)
(disj set) (disj set key) (disj set key & ks)

和相当相似的语义。为什么这些都没有被相同的功能覆盖?我能看到的唯一支持这一点的论点是 map 同时具有 (assoc map key val)(conj map [key val])添加条目,而集合仅支持 (conj set k) .

我可以编写一个单行函数来处理这种情况,但是 Clojure 在很多时候都非常优雅,以至于当它不是时它真的让我感到不安:)

最佳答案

只是为了抵消 Arthur 的回答: conj 的定义更早(名称 conj 出现在 core.clj 的第 82 行,而 disj 的名称为 1443 , dissoc 的名称为 1429 ),但适用于所有 Clojure 集合类型。 :-) 显然它不使用协议(protocol)——而是使用常规的 Java 接口(interface),就像大多数 Clojure 函数一样(事实上,我相信目前 Clojure 中唯一使用协议(protocol)的“核心”功能是 reduce/reduce-kv )。

我猜想这是由于审美选择,实际上可能与 map 支持 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
)

那应该返回 {}{:foo 1 [:foo 1] 2} 还是 {{:foo 1 [:foo 1] 2} 3}conj 愉快地接受 [:foo 1]{:foo 1 [:foo 1] 2} 作为 conj 到 map 上的东西。 (带有两个映射参数的 conj 表示 merge ;实际上 merge 是根据 conj 实现的,添加了对 nil 的特殊处理)。

因此,为 map 设置 dissoc 可能是有意义的,这样很明显它会删除一个键,而不是“可能是 conj 的东西”。

现在,理论上 dissoc 可以在集合上工作,但也许人们可能期望它们也支持 assoc ,这可以说是没有意义的。值得指出的是,向量确实支持 assoc 而不是 dissoc ,所以它们并不总是在一起;这里肯定有一些审美张力。

关于clojure - 为什么 `disj` 和 `dissoc` 在 Clojure 中有不同的功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28844647/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com