请在2024年Clojure状态调查!中分享您的看法。

欢迎!请查看关于页面,了解更多关于这个工作方式的信息。

0 投票
data.int-map
编辑

这是一个问题,在Clojure中,我们通常有HashMap,允许在这些HashMap上关联任何类型的关键字,然后我们还有一些更适合特定关键字的专业化映射。然而,大多数都允许在常规范围之外关联关键字,并在操作会破坏数据结构的不变量时优雅地回退到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"}]

另一方面,struct-maps允许关联,但不允许删除

(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"]

另一个例子是ArrayMaps,随着它们的增长最终会变成HashMap。这并不完全相同,因为.InputStreamReader中没有任何特定的关键字,但从更广泛的角度来看,即当操作违反了不变量或性能预期时,回退到通用的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实现,它持有一个额外的映射,在其中存储不属于结构定义的额外键/值对

final IPersistentMap ext;

同样,也可以在PersistentIntMap中实现这一点

(deftype PersistentIntMap
  [^INode root
   ^long epoch
   meta
   ^IPersistentMap ext]
  ;; ...

您怎么看?

还有,关于int-sets的相同问题


编辑
我认为这件事中最棘手的部分可能是与强制转换的行为有关。例如,你可以将一个int、BigInt或short插入到int-map中,并对其进行转换成long。但是这与HashMap的行为不同,HashMap只是存储传入的键。这本身可能足以使整个想法成为泡影。尽管如此,仍有思考的价值。

1 个答案

+1 个投票

选择
 
最佳答案

int-map/set的约束条件是它们具有整数字段,并且可以为此类用途获得性能优势。如果你需要这样的功能,你应该使用int-map。如果你不需要,你应该使用标准的map。

因此,我 thinks 将非整数字段添加到int-map中会抛出异常是有益的,这一点不应该改变。

...