Zach Tellman's potemkin library includes several useful ways to tweak deftypes and defrecords. I wish Clojure itself provided more ways to do this, but in the meantime, potemkin is the best way to create something custom, like a deftype that behaves mostly like defrecord with some different hashing and equality behavior.
On Thu, Jun 11, 2015 at 11:36 AM, Mars0i <marsh...@logical.net> wrote: > 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. > -- 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.