2012-02-10 32 views
6

Tôi thấy hành vi của Clojure gây nhầm lẫn về sự bình đẳng giữa các bản đồ và bản ghi. Trong ví dụ đầu tiên này, chúng ta có hai loại khác nhau có cấu trúc ngang nhau. Sự bình đẳng = function trả về true:Bản đồ và hồ sơ bình đẳng trong Clojure

user> (defn make-one-map 
     [] 
     {:a "a" :b "b"}) 
#'user/make-one-map 
user> (def m1 (make-one-map)) 
#'user/m1 
user> m1 
{:a "a", :b "b"} 
user> (def m2 {:a "a" :b "b"}) 
#'user/m2 
user> m2 
{:a "a", :b "b"} 
user> (= m1 m2) 
true 
user> (type m1) 
clojure.lang.PersistentArrayMap 
user> (type m2) 
clojure.lang.PersistentHashMap 

Trong ví dụ thứ hai chúng ta có một hashmap và một kỷ lục mà có cấu trúc tương đương nhưng = function trả về false:

user> (defrecord Titi [a b]) 
user.Titi 
user> (def titi (Titi. 1 2)) 
#'user/titi 
user> titi 
#user.Titi{:a 1, :b 2} 
user> (= titi {:a 1 :b 2}) 
false 

Tại sao là những khác biệt? Tôi đang sử dụng Clojure 1.3 và tôi thấy chúng thực sự khó hiểu.

Trả lời

14

Từ docstring cho defrecord:

Bên cạnh đó, defrecord sẽ xác định loại và giá trị dựa trên =, và sẽ định nghĩa Java .hashCode và Equals phù hợp với hợp đồng cho java.util .Bản đồ.

Vì vậy, khi sử dụng =, loại được tính đến. Bạn có thể sử dụng thay vì .equals:

user> (.equals titi {:a 1 :b 2}) 
true 
+0

Tại sao các bản sao của PersistentArrayMap và PersistentHashMap bằng = sau đó vì hàm kiểu cho biết chúng không cùng loại? – z1naOK9nu8iY5A

+7

Lời hứa "type-and-value-based =" được ghi trong chuỗi doc 'defrecord' và áp dụng cho các bản ghi. Các bản đồ thông thường, mặt khác, được cho là tham gia vào một lược đồ dựa trên giá trị, và chúng làm, đến điểm mà '(= (hash-map: foo 1: bar 2) (sắp xếp bản đồ: foo 1: bar 2)) 'và' (= (java.util.HashMap. {: foo 1: bar 2}) {: foo 1: bar 2}) 'đều là' true'. –

8

một PersistentArrayMapPersistentHashMap là khái niệm giống nhau - như ArrayMap phát triển, nó sẽ tự động được chuyển đổi để một HashMap vì lý do hiệu suất. Mã cấp người dùng thường không nên phân biệt giữa hai mã. Mặt khác,

Mặt khác, defrecord không giống với một trong các bản đồ khác. Đây là một loại riêng biệt có thể thực hiện các giao diện hoàn toàn khác nhau và không nên tự động thay thế bằng một số loại bản đồ khác. Nó không phải là khái niệm tương đương với một bản đồ bình thường, do đó, = trả về false.

Các vấn đề liên quan