目前,Clojure 的解构实现会将任何满足 clojure.core/seq? 的值创建为 hash-map。我争辩说这有一个不希望产生的副作用,即使得在同时是一个自定义的关联类型和一个序列的关联类型上进行解构变得不可能。这在尝试解构标签值类的实例时出现,这些实例在模式匹配方面行为就像 [k v] 序列,但由于 v 已知是映射,因此在映射部分上也具有关联性,以避免更新保留标签的语法开销。
;; 此类型的一个草图
(deftype ATaggedVal [t v]
clojure.lang.Indexed
(nth [self i] (nth self i nil))
(nth [self i o] (case i (0) t (1) v o))
clojure.lang.Sequential
clojure.lang.ISeq
(next [this] (seq this))
(first [this] t)
(more [this] (.more (seq this)))
(count [this] 2)
(equiv [this obj] (= (seq this) obj))
(seq [self] (cons t (cons v nil)))
clojure.lang.Associative
(entryAt [self key] (.entryAt v key))
(assoc [_ sk sv] (ATaggedVal. t (.assoc v sk sv)))
clojure.lang.ILookup
(valAt [self k] (.valAt v k))
(valAt [self k o] (.valAt v k o))
clojure.lang.IPersistentMap
(assocEx [_ sk sv] (ATaggedVal. t (.assocEx v sk sv)))
(without [_ sk] (ATaggedVal. t (.without v sk))))
因此使用这样的事物,
(let [{:keys [x]} (ATaggedVal. :foo {:x 3 :y 4})] x)
;; 期望 3
=> nil
由于对于任何满足 clojure.core/get 将表现行为的类型 T,T 应该满足 clojure.core/map?, должно было быть в correto simplesmente mudar o comportamento da destruturação para construir um hash-map apenas se map? não for satisfeito.
附带补丁实现此更改。