Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Distinguishing a record instance from a map

Tags:

clojure

I'm trying to call clojure.walk/stringify-keys on a map that might include record instances. Since stringify-keys is recursive, it attempts to convert the keys on my record, (since (map? record-var) is true) which causes an error. Is there any way to tell if a var is a record rather than just a Clojure map? I d like to provide my own implementation of stringify-keys that is record-aware.

The current implementation of stringify-keys causes the following:

(use '[clojure.walk :only [stringify-keys]])

(defrecord Rec [x])    

(let [record (Rec. "foo")
      params {:x "x" :rec record}]
    (stringify-keys params))

This causes the following exception: UnsupportedOperationException Can't create empty: user.Rec user.Rec (NO_SOURCE_FILE:1)

like image 567
ralfonso Avatar asked May 14 '12 18:05

ralfonso


2 Answers

Records seem to implement the IRecord marker interface:

user=> (defrecord Rec [x])    
user.Rec

user=> (require '[clojure.reflect :as r])
nil
user=> (:bases (r/reflect Rec))
#{java.io.Serializable clojure.lang.IKeywordLookup clojure.lang.IPersistentMap clojure.lang.IRecord java.lang.Object clojure.lang.IObj clojure.lang.ILookup java.util.Map}

user=> (instance? clojure.lang.IRecord (Rec. "hi"))
true

Update 1.6 now has the record? functions

like image 93
DanLebrero Avatar answered Oct 23 '22 00:10

DanLebrero


you can check the type of each member and see if it is really a map or something else (where something else is presumed to be a record)

user> (type {:a 1 :b 2})
clojure.lang.PersistentArrayMap
like image 1
Arthur Ulfeldt Avatar answered Oct 23 '22 02:10

Arthur Ulfeldt