2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!请参阅 关于 页面以了解该功能的更多信息。

0
Collections
目前,Clojure 的解构实现会从遇到的满足 clojure.core/seq? 的任何值创建一个哈希表。我认为这会产生不希望的不利影响,使得无法在也是 Seq 的自定义关联类型上应用解构。这出现在尝试解构标记值类的实例时,该类在模式匹配时行为类似于 [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?,解构的行为应该只是当 map? 不满足时才简单地改变以构建哈希表。

附加的补丁实现了这个改变。

4 答案

0

评论者:alexmiller

可能还需要观察CLJ-1778这个也可能导致这个功能不再适用的bug。

您能否在描述中添加一个不工作的示例吗?

0
_评论者:ragge_

当前CLJ-1778的补丁并没有解决这个问题。

我觉得这个想法听起来很合理,如果我们map解构的值已经是一个map(通过{{map?}}确定),我们不需要通过调用{{seq}}和{{HashMap/create}}来创建一个新的map,除非有相当充分的理由要使用确切的这个map实现(我看不出来)。
除非有非常充分的理由让它必须是那个map实现(我看不出来)。
除非有真正充分的理由要让它正好是这个map实现(我看不出来)。
如果它必须要是这个map实现,那么我看不到一个理由。
我不认为当前的补丁是好的,因为它对map解构的行为做出了(不必要的)破坏性改变。

我认为当前的补丁并不好,因为它在map解构上做出了(不必要的)破坏性改变。
之前,解构不可序列值返回nil,但此补丁使{{seq}}始终在值上被调用,对于非序列类型,这将会抛出一个异常。应该很容易更改补丁以保留原始行为。
以前,解构非序列值返回nil,但现在,{{seq}}始终在值上被调用,对于不能序列化的类型,这将抛出一个异常。应该非常容易修改补丁以保留原始行为。
1.8.0-master















0
_评论者:arrdem_

我认为破损的行为最多是源于实现的未定义行为,而无法转换为异常至少比原始实现的沉默nil行为更为明确。

我个人更愿意逻辑上扩展解构检查到{{(cond map? x seq? (hash-map (seq x)) :else (throw "Failed to destructure non-map type"))}},但我觉得这个改动足够大,可能会显著降低这个补丁被接受的机会。
0
参考: https://clojure.atlassian.net/browse/CLJ-1803 (由arrdem报告)
...