tags:

views:

162

answers:

2

When defining a struct type and instance, I can print the value and get the "struct" implementation type:

(defstruct person :name :age)
(def p (struct person "peter" 30))

user=> p
{:name "peter", :age 30}
user=> (type p)
clojure.lang.PersistentStructMap

But is it possible to tell whether p is an instance of the struct type "person"?

+7  A: 

See: http://groups.google.com/group/clojure/browse_thread/thread/a5e0ba6480d04829/3fbd539b807a506d?q=struct+type+group:clojure#3fbd539b807a506d

In general the group archives are a treasure chest...

Note: The functionality of structs is replaces by records. There this is not a problem anymore, because records really define new type and you can check with instance? whether something is of record of a certain type.

kotarak
+1 for pointing out a great resource!
mikera
OK, thanks. Records seems to be the way to go - just need to upgrade Clojure.
j-g-faustus
Well. 1.2 is not released, yet. So YMMV.
kotarak
+4  A: 

A bit ugly, but it works:

(require '[clojure.contrib.java-utils :as cj])

(defn struct-instance? [struct-def sm]
  (= (cj/wall-hack-field clojure.lang.PersistentStructMap "def" sm)
     struct-def))

(struct-instance? person p)
; => true

(struct-instance? person (conj p [:foo 1] [:bar 2]))
; => true

(defstruct foo :k1 :k2)
(struct-instance? foo p)
; => false

Stuff from clojure.contrib.java-utils will be available in 1.2 in part in clojure.java, in part in clojure.contrib.java (I guess?), and also in clojure.contrib.java-utils for backward compatibility... Although the details might still change. At any rate, Meikel is right about defrecord replacing defstruct, so if you're working on 1.2, prefer that.

Michał Marczyk
You certainly seem to know your way around Clojure ;)I'm at 1.1 for the moment, but the 1.2 defrecord looks like a better long-term solution. Still, thanks for the hack and the pointer to java-utils :)
j-g-faustus