2011-10-06 89 views
5

最近,我問了一下Clojure中的地圖組合鍵:How can you implement Composite keys in clojure? ...在java中重寫「equals」的clojure等價物是什麼?

的回答是,他們的工作與Java類似鑰匙 - 如果事情覆蓋「等於」,那麼它可以有效地作爲重點使用。

我想知道:是否有宏允許我們覆蓋「等於」自定義數據結構?例如,假設我想使用Map作爲關鍵字,並將唯一性定義爲「如果此地圖包含與另一個地圖相同的2個或更多元素,則它們是相同的」。我如何覆蓋地圖的默認行爲?

在java中,我發現這個工具在製作具有數千個豆類作爲關鍵字的高速地圖時非常強大。

回答

4

這不是說clojure系列覆蓋等於;凌駕平等發生幾乎所有你做一些有趣的事情。 Clojure類型提供了一個旨在使整個語言保持一致的equals的實現(可以說是以一種Java平等意圖被使用的方式)。這意味着,「平等」的東西應該是單數的套裝和單一的地圖,總是,無處不在。語言設計依賴於此。 Clojure 1.3進行了一些明確的非後向兼容更改以接近理想狀態。

違背平等的預期行爲很可能會在某處造成麻煩。而且,當你真的需要它們時,使用你自己的套裝式複合材料並不難,而不會迫使你的意願與核心相等。

也就是說,如果你真的想要的話,你可以使用很多Java互操作函數和宏來破壞等號系統。以http://clojure.org/datatypes爲起點。

1

這在Clojure和Java中都很瘋狂。 不要這樣做。你將打破Object類和Map接口的契約;如果他們使用您的自定義地圖類,各種東西將完全崩潰。如果您聲明兩個對象是equal,那麼它們的哈希碼必須相同,否則保存它們的HashMap將無法應對。當然,您可以將所有內容散列爲0,但您的高性能地圖可以使用 - 現在它已成爲鏈接列表。也就是說,你可以在Clojure或Java中使用sorted-map(或SortedMap)(或分別使用SortedMap)和自定義比較器來做類似的事情。然而,如果你選擇了一個比較器,其實不然,實際上實現了等式,而是某種「模糊等式」。

+0

只要你重寫你的散列函數,重寫equals也是可以的。一點也不瘋狂 - 標準,普通的好設計。任何好的GUI/lint類型的程序都會提醒你重寫一個,如果你重寫另一個。使用比較器有點難以理解,因爲它會將知識從你的課堂輸出到另一個(比較器) –

+2

這看起來有點像範例衝突。有些人認爲「自我包容的對象,問他們是否平等」,而其他人則認爲「不變價值的構成」在等於是普遍的概念。 –

+3

我並不反對重寫equals - 在Java中顯然通常是必需的。以他提出的方式覆蓋它*是一個可怕的想法,因爲不可能編寫一個'hashCode'函數,該函數符合決定讓equals等於任何至少與這個鍵共享兩個鍵的映射返回true的結論。 – amalloy

5

爲了有助於增加對此討論的清晰度,在Java中,通常覆蓋hashCodeequals。例如,您試圖跟蹤有姓名但可能有暱稱的員工。目標是確保這些員工不會重複。在這種情況下,我會覆蓋equalshashCode以僅查看員工的ID。當這些員工進入Set數據結構時,他們不會被複制。在Clojure中,你可以這樣做:

(deftype Employee [name id] 
    Object 
    (equals [a b] (= (.id a) (.id b))) 
    (hashCode [this] (.hashCode (.id this))) 
    (toString [this] (.name this))) 

(def vince (Employee. "Vince" 42)) 

(def vincent (Employee. "Vincent" 42)) 

(def tony (Employee. "Tony" 2)) 

(into #{} [vince vincent tony]) 

但你不妨去追求「純Clojure的」數據結構的解決方案,而不是去的哈希碼,平等相待,互操作的Java之路。

+0

「純Clojure」數據結構解決方案是什麼樣的? –

相關問題