defrecord and overriding "empty"

275 views
Skip to first unread message

Nathan Sorenson

unread,
Sep 27, 2011, 3:48:02 AM9/27/11
to Clojure
I'm using clojure.walk/postwalk to rewrite terms in nested data
structures. However, I am unable to do this with types as defined by
defrecord, because they specify that the function "empty" throw a not-
implemented exception.

If I were able to over-ride this default implementation of 'empty' I
believe I could still use postwalk to rewrite my custom records (as
they happily implement 'into' which works as expected.)

This was my obvious first attempt:

(defrecord TypeVar [guid name]
clojure.lang.IPersistentCollection
(empty [coll] (TypeVar. 0 nil)))

Which fails due to:

"Duplicate method name&signature in class file types/TypeVar"
[Thrown class java.lang.ClassFormatError]

I would prefer not to fall back on deftype as I do wish these objects
to behave as maps. I also could write my own version of postwalk that
doesn't call 'empty' on my custom-defined records, but it would be
nice to make my types adhere to the contract of IPersistentCollection
as much as possible.

David Nolen

unread,
Sep 27, 2011, 1:07:44 PM9/27/11
to clo...@googlegroups.com
The problem is what does empty mean in the context of defrecord? A new instance of a defrecord is not "empty", it has those fields and they are set to nil.

David

Nathan Sorenson

unread,
Sep 27, 2011, 1:54:21 PM9/27/11
to clo...@googlegroups.com
You're right that my use isn't strictly returning a collection with a size of zero-- I'm treating empty more like 'default'. I'm thinking of its use in clojure.walk, which simply creates a "blank" version of an arbitrary collection in which to place the altered sub-forms. I can't find any other usages of 'empty' in the std lib.

I agree it's a bit of a mismatch, as 'walk' won't be able to alter the built-in keys of a record, but you wouldn't expect that to happen if you were using records.

Should IPersistentCollection even be defining 'empty', if one of the language's key data types doesn't support it? I think it would be better to either pull 'empty' into it's own protocol so clojure.walk doesn't match on IPersistentCollection when walking a data structure with the false expectation that it can create an empty version, or rename 'empty' it to something that records can implement, like 'default.'

David Nolen

unread,
Sep 27, 2011, 2:06:37 PM9/27/11
to clo...@googlegroups.com
On Tue, Sep 27, 2011 at 1:54 PM, Nathan Sorenson <nd...@sfu.ca> wrote:
Should IPersistentCollection even be defining 'empty', if one of the language's key data types doesn't support it? I think it would be better to either pull 'empty' into it's own protocol so clojure.walk doesn't match on IPersistentCollection when walking a data structure with the false expectation that it can create an empty version, or rename 'empty' it to something that records can implement, like 'default.' 

This is a fair point. ClojureScript fixes this by providing IEmptyableCollection.

David 

David Nolen

unread,
Dec 15, 2012, 5:57:53 PM12/15/12
to clo...@googlegroups.com
In core.logic we have a protocol called IUninitialized that you can implement. That works well enough for our needs.

On Saturday, December 15, 2012, Joseph Smith wrote:
Well here I am over a year later with the same problem. I'm curious, what was your solution for the time being?
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
Reply all
Reply to author
Forward
0 new messages