I think that the following is all correct, but I could be wrong about 
something.

The datatypes page at clojure.org <http://clojure.org/datatypes> says: 
"defrecord provides ... value-based equality and hashCode", while deftype 
does not.   So
(defrecord Rec [x])
(= (Rec. 42) (Rec. 42)) ;=> true
but
(deftype Typ [x])
(= (Typ. 42) (Typ. 42)) ;=> false.
This also means, as I understand it, that data structures that use 
hashing--maps and sets, for example--hash on value for records, but on 
identity for types.  I believe that the same is true when Java hashtables 
compare records, or compare types, although I haven't carefully tested this.

It makes sense that the primary, most fully functional user-definable 
datatypes in Clojure should use value-based equality; that's fully in the 
spirit of a functional language, and is very convenient in many contexts, 
and hashing should follow the equality semantics of the datatypes.  You can 
always use identical? if you want to test records for identity rather than 
equality.

However, you can't tell maps and sets to use identity for records, afaik.  
This makes records undesirable if you only care about identity, and need to 
use a data structure that uses hashing, and care about performance, because 
value-based hashing is presumably a lot slower than identity-based hashing 
(which is what my experiments seem to show).

On the other hand, records are obviously way, way, more convenient than 
types in many contexts because the functionality provided by deftype is so 
bare-bones.  It really bothers me that I have to choose between speed and 
using convenient, idiomatic functionality (defrecord) that is one of 
several significant reasons that I love Clojure.  (This is in an 
application in which value-based equality would *never* be what I wanted 
for my datatypes.)

Should there be an alternative?  Either a way to define e.g. a special kind 
of set that uses identity rather than value for records, or a way to make 
records use identity for equality, or another datatype that's just like 
defrecord but ..., or a way to get more functionality with deftype, or 
...?  (I don't think that Clojure should include every option or 
functionality that someone thinks might be convenient in some context.  
Another reason that I love Clojure is that it *doesn't* do that, but 
instead provides limited, well-thought out options that allow a lot of 
flexibility.)

In an earlier thread 
<https://groups.google.com/forum/#!topic/clojure/EdjnSxRkOPk>, Stephen Yi 
pointed out that although you're allowed to override some Object methods in 
defrecord, you can't override Object.equals and Object.hashCode.  It isn't 
documented, but the compiler throws an exception if you try it.  That makes 
quite a bit of sense, since changing the meaning of equality for a datatype 
would be an easy way to introduce confusing bugs.  On the other hand, if 
you do override Object.equals and Object.hashCode for defrecord, you 
probably know that you're doing something weird, and that you'd better take 
precautions, if necessary, to avoid later confusion.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to