2024年Clojure调查问卷!中分享您的想法。

欢迎!请参阅关于页面,了解一些关于它是如何工作的更多信息。

0
data.int-map
修改

这是一个问题,在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

by
编辑 by
我觉得这最难的部分可能是关于类型转换行为。例如,你可以将 int、BigInt 或 short 插入 int-map 中,它将被转换为 long。但这与 HashMaps 的行为不同,HashMaps 只存储传递给它的键。这本身可能足以使整个想法失败。尽管如此,仍然值得思考。

1 个答案

+1
by
选择 by
 
最佳答案

int-map/set 的声明约束是它们必须有整数键,并且可以为此用例获得性能优势。如果你想这样做,你应该使用 int-map。如果不这样,你应该使用标准映射。

所以,我认为向 int-map 添加非整数字符串会抛出异常,这一点不应该改变。

...