Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where should I use defrecord in clojure?

Tags:

clojure

I use many maps and structs in my clojure programs. What are the benefits (apart from performance) of converting these to defrecords?

like image 920
yazz.com Avatar asked Jan 01 '11 18:01

yazz.com


People also ask

What is Defrecord Clojure?

Clojure allows you to create records, which are custom, maplike data types. They're maplike in that they associate keys with values, you can look up their values the same way you can with maps, and they're immutable like maps.

What does Gen class do in Clojure?

The generated class automatically defines all of the non-private methods of its superclasses/interfaces. This parameter can be used to specify the signatures of additional methods of the generated class.

What is reify Clojure?

The method bodies of reify are lexical closures, and can refer to the surrounding local scope. reify differs from proxy in that: Only protocols or interfaces are supported, no concrete superclass. The method bodies are true methods of the resulting class, not external fns.

Are there classes in Clojure?

Clojure has gen-class, reify, proxy and also deftype and defrecord to define new class-like datatypes.


2 Answers

I consider structs to be effectively deprecated so I don't use them at all.

When I have a fixed set of well-known keys used in many map instances, I usually create a record. The big benefits are:

  • Performance
  • Generated class has a type that I can switch on in multimethods or other situations
  • With additional macro machinery around defrecord, I can get field validation, default values, and whatever other stuff I want
  • Records can implement arbitrary interfaces or protocols (maps can't)
  • Records act as maps for most purposes
  • keys and vals return results in stable (per-creation) order

Some downsides of records:

  • Because records are Java class instances (not Clojure maps), there is no structural sharing so the same record structure will likely use more memory than the equivalent map structure that has been changed. There is also more object creation/destruction as you "change" a record although the JVM is designed specifically to eat this kind of short-lived garbage without breaking a sweat.
  • If you are changing records during development you probably need to restart your REPL more frequently to pick up those changes. This is typically only an issue during narrow bits of development.
  • Many existing libraries have not been updated to support records (postwalk, zip, matchure, etc etc). We've added this support as needed.
like image 161
Alex Miller Avatar answered Sep 25 '22 03:09

Alex Miller


Stuart Sierra recently wrote an interesting article on "Solving the Expression Problem with Clojure 1.2", which also contains a section on defrecord:

http://www.ibm.com/developerworks/java/library/j-clojure-protocols/index.html#datatypes

I think the whole article is a good starting point for understanding protocols and records.

like image 31
Michael Kohl Avatar answered Sep 21 '22 03:09

Michael Kohl