这是一个问题,在Clojure中,我们有典型的HashMap,允许在任何键上使用assoc操作,然后我们有一些更专门用于特定键的map类型。然而,它们大多数也可以允许在常规范围外使用assoc键,并在操作会破坏数据结构的不变量时优雅地回退到HashMap。以下是一些示例:
记录是开放的,当删除记录字段时会回退到HashMap
(defrecord Person [name lang])
;; => clojure.data.int_map_test.Person
(let [p (->Person "john" "en_CA")]
[p (assoc p :foo :bar) (dissoc p :lang)])
;; =>
;; [#clojure.data.int_map_test.Person{:name "john", :lang "en_CA"}
;; #clojure.data.int_map_test.Person{:name "john", :lang "en_CA", :foo :bar}
;; {:name "john"}]
另一方面,结构化map是开放的,但在删除时不允许关闭
(let [sm (struct-map (create-struct :name :lang) :name "John" :lang "en_CA")]
[(assoc sm :foo "bar")
(try (dissoc sm :lang) (catch Exception e (.toString e)))])
=> [{:name "John", :lang "en_CA", :foo "bar"}
"java.lang.RuntimeException: Can't remove struct key"]
另一个例子是ArrayMap,当它们变大时最终会变成HashMap。这并不完全相同,没有特定的键在map的范围之外,但更普遍地说,当操作违反了不变量或性能预期时,会回退到通用的HashMap。
这让我想知道,人们是如何看待int-map/int-set的,当尝试添加非整数键时,它会抛出异常?
(assoc (i/int-map 1 2) :a "b")
ClassCastException class clojure.lang.Keyword cannot be cast to class java.lang.Number
是否应该修改它以回退到HashMap?这似乎与Clojure开放数据结构的哲学更加一致。
它可以与PersistentStructMap
类似实现,它可以持有附加的map,用于存储不属于结构定义的额外键值对
final IPersistentMap ext;
同样可以在PersistentIntMap中实现这一点
(deftype PersistentIntMap
[^INode root
^long epoch
meta
^IPersistentMap ext]
;; ...
您怎么看?
此外,同一个问题,但对于int-set