chan 上是否正确定义了平等?

Is equality properly defined on chan?

我想维护一个频道集合,能够添加和删除频道。是否定义了相等性以便我可以正确地 conjdisj

换句话说,这总是有效吗?

=> (def chan-collection (atom #{}))
=> (def my-chan-1 (chan))
=> (def my-chan-2 (chan))
=> @chan-collection
#{}
=> (swap! chan-collection conj my-chan-1)
=> @chan-collection
#{#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@6ec3a2f6>}
=> (swap! chan-collection conj my-chan-2)
=> @chan-collection
#{#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@382830a1>
  #<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@6ec3a2f6>}
=> (swap! chan-collection disj my-chan-1)
=> @chan-collection
#{#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@382830a1>}
=> (swap! chan-collection disj my-chan-2)
=> @chan-collection
#{}

是的,这是真的,改变它会破坏一切。

如果频道是相同的频道对象,则频道是 identical?,因此在所有情况下都是平等的。 chans 的所有其他比较都明确 not 相等,这对您有好处。您希望移除是移除您要求移除的 确切的 频道,而不是具有相同内容的等效频道。所以幸运的是不相同的chans也不相等

user> (= (chan) (chan))
false
user> (identical? (chan) (chan))
false
user> (identical? my-chan-1 (chan))
false
user> (identical? my-chan-1 my-chan-1)
true
user> 
user> (= my-chan-1 my-chan-1)
true

在一般情况下 "Clojure world" 这同样 属性 适用于所有 身份而不是价值 的事物。身份具有随时间变化的值,因此如果两个 identities 在您询问时碰巧包含相同的值,则说它们相等是没有意义的,即使这可能只对您而言是正确的,永远不会对于其他人。比较身份中的值更有意义。例如像chans一样,具有相同值的原子也不相等,这是clojure的基本属性,永远不会改变。

user> (let [a (atom 1)]
        (= a a))
true
user> (= (atom 1) (atom 1))
false

如果你想删除它们,就像你在上面所做的那样,通过将你想要删除的确切 chan 作为参数提供给 disj,而不是像 "remove the channel with 42 in it"

这样的其他概念

如果我们做同样的设置:

user> (require '[clojure.core.async :refer [<! <!! >! chan]])
nil
user> (def chan-collection (atom #{}))
#'user/chan-collection
user> (def my-chan-1 (chan))
#'user/my-chan-1
user> (def my-chan-2 (chan))
#'user/my-chan-2
user> (swap! chan-collection conj my-chan-1 my-chan-2)
 #{#object[clojure.core.async.impl.channels.ManyToManyChannel 0x35b61c71 "clojure.core.async.impl.channels.ManyToManyChannel@35b61c71"] #object[clojure.core.async.impl.channels.ManyToManyChannel 0x240e86d5 "clojure.core.async.impl.channels.ManyToManyChannel@240e86d5"]}

然后要求删除 "the empty chan":

user> (swap! chan-collection disj (chan))
 #{#object[clojure.core.async.impl.channels.ManyToManyChannel 0x35b61c71 "clojure.core.async.impl.channels.ManyToManyChannel@35b61c71"] #object[clojure.core.async.impl.channels.ManyToManyChannel 0x240e86d5 "clojure.core.async.impl.channels.ManyToManyChannel@240e86d5"]}

我们可以验证它什么也没做。