Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure record constructors not first class?

Apparently, you can't call apply with a record constructor:

(defrecord Foo. [id field])

(apply Foo. my-list)

fails at read time because it is not expecting Foo. in that place.

The only obvious workaround I could think of was to add a factory function:

(make-foo [id field] (Foo. id field))

which can be apply'ed of course.

Am I missing anything? I'd expect this from C#/Java but just thought it was a bit disappointing in Clojure...

like image 302
Kurt Schelfthout Avatar asked Feb 16 '11 12:02

Kurt Schelfthout


1 Answers

Circling back on this post-1.3....

In Clojure 1.3, defrecord creates two generated constructor functions. Given:

(defrecord Person [first last]) 

this will create a positional constructor function ->Person:

(->Person "alex" "miller")

and a map constructor function map->Person:

(map->Person {:first "string"})

Because this is a map, all keys are optional and take on a nil value in the constructed object.

You should require/use these functions from the ns where you declare the record, but you do not need to import the record class as you would when using the Java class constructor.

More details:

  • http://dev.clojure.org/display/design/defrecord+improvements
  • http://groups.google.com/group/clojure/browse_thread/thread/ce22faf3657ca00a/beb75e61ae0d3f53
like image 115
Alex Miller Avatar answered Sep 28 '22 08:09

Alex Miller