Question on defrecord

2010-08-11 Thread Shantanu Kumar
I tried to assign a data type to a var and then instantiate it using
the var, but it doesn't seem to work:

user= (defrecord X [])
user.X

user= (X.)
#:user.X{}

user= X
user.X

user= (def hey X)
#'user/hey

user= (hey.)
java.lang.IllegalArgumentException: Unable to resolve classname: hey
(NO_SOURCE_FILE:59)

user= (new X)
#:user.X{}

user= (new hey)
java.lang.IllegalArgumentException: Unable to resolve classname: hey
(NO_SOURCE_FILE:61)

user= (apply new hey)
java.lang.Exception: Unable to resolve symbol: new in this context
(NO_SOURCE_FILE:62)

Can anybody help me understand how to accomplish this when using the
var? This will give me a generic way to instantiate the type when I
know the parameters.

Regards,
Shantanu

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@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+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Question on defrecord

2010-08-11 Thread Krukow


On Aug 11, 7:03 pm, Shantanu Kumar kumar.shant...@gmail.com wrote:
 I tried to assign a data type to a var and then instantiate it using
 the var, but it doesn't seem to work:

 user= (defrecord X [])
 user.X

 user= (X.)
 #:user.X{}

 user= X
 user.X

 user= (def hey X)
 #'user/hey

 user= (hey.)
 java.lang.IllegalArgumentException: Unable to resolve classname: hey
 (NO_SOURCE_FILE:59)

 user= (new X)
 #:user.X{}

 user= (new hey)
 java.lang.IllegalArgumentException: Unable to resolve classname: hey
 (NO_SOURCE_FILE:61)

 user= (apply new hey)
 java.lang.Exception: Unable to resolve symbol: new in this context
 (NO_SOURCE_FILE:62)

 Can anybody help me understand how to accomplish this when using the
 var? This will give me a generic way to instantiate the type when I
 know the parameters.

 Regards,
 Shantanu

There is no way to do this without using Java reflection, see e.g.

user= (defrecord A [])
user.A
user= (def x A)
#'user/x
user= (.newInstance x)
#:user.A{}
user=

Note .newInstance is a simple example and only works for no-arg
constructor.


See, e.g.,
http://download.oracle.com/javase/tutorial/reflect/member/ctorInstance.html





-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@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+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Question on defrecord

2010-08-11 Thread Chouser
On Wed, Aug 11, 2010 at 1:03 PM, Shantanu Kumar
kumar.shant...@gmail.com wrote:
 I tried to assign a data type to a var and then instantiate it using
 the var, but it doesn't seem to work:

 user= (defrecord X [])
 user.X

 user= (X.)
 #:user.X{}

 user= X
 user.X

 user= (def hey X)
 #'user/hey

 user= (hey.)
 java.lang.IllegalArgumentException: Unable to resolve classname: hey
 (NO_SOURCE_FILE:59)

 user= (new X)
 #:user.X{}

 user= (new hey)
 java.lang.IllegalArgumentException: Unable to resolve classname: hey
 (NO_SOURCE_FILE:61)

 user= (apply new hey)
 java.lang.Exception: Unable to resolve symbol: new in this context
 (NO_SOURCE_FILE:62)

 Can anybody help me understand how to accomplish this when using the
 var? This will give me a generic way to instantiate the type when I
 know the parameters.

The problem is that X. is a special form, so when you say
hey. it's looking for a class literally named hey.

The best solution is to provide for each defrecord a real Clojure
function to act as a factory.  There are several places that such
a function can be helpful, and in real-world code you almost
always run into at least one of them:

(defrecord X [])
(defn new-X [] (X.))

(def hey new-X)

(hey)
;= #:user.X{}

If you don't like the idea of a named factory function for each
record type, you can create an anonymous fn on the fly instead:

(defrecord X [])

(def hey #(X.))

(hey)
;= #:user.X{}

Note in either case when you define the factory fn (named or
not), you need to specify all the args the real record
constructor requires.

--Chouser
http://joyofclojure.com/

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@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+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Question on defrecord

2010-08-11 Thread Stuart Halloway
Hi Shantanu,

It depends on exactly what you want when you say accomplish this. The Clojure 
(new Foo) and (Foo.) forms map to Java new. You cannot call Java new 
generically, from any Java language. You have to have a class already in hand.

If you want genericity at compilation time, you could write a macro that 
expands to a new form.

But probably what you want is genericity at runtime. For this, you need to use 
Java reflection to instantiate the class. There is a previous thread on this 
that includes some sample code [1], but nothing in Clojure (yet). 

It is fairly easy to write a reflective factory that is good enough for a 
single app or library, but harder to write one that is general enough to be in 
Clojure proper. There is an outstanding ticket that would cover this [2] and it 
will probably get into the release of Clojure after 1.2.

Stu

[1] 
http://groups.google.com/group/clojure/browse_thread/thread/bd7be7bd373eadba/4bc3e7a2099ad72d
[2] 
https://www.assembla.com/spaces/clojure/tickets/374-print-read-syntax-for-defrecords

 I tried to assign a data type to a var and then instantiate it using
 the var, but it doesn't seem to work:
 
 user= (defrecord X [])
 user.X
 
 user= (X.)
 #:user.X{}
 
 user= X
 user.X
 
 user= (def hey X)
 #'user/hey
 
 user= (hey.)
 java.lang.IllegalArgumentException: Unable to resolve classname: hey
 (NO_SOURCE_FILE:59)
 
 user= (new X)
 #:user.X{}
 
 user= (new hey)
 java.lang.IllegalArgumentException: Unable to resolve classname: hey
 (NO_SOURCE_FILE:61)
 
 user= (apply new hey)
 java.lang.Exception: Unable to resolve symbol: new in this context
 (NO_SOURCE_FILE:62)
 
 Can anybody help me understand how to accomplish this when using the
 var? This will give me a generic way to instantiate the type when I
 know the parameters.
 
 Regards,
 Shantanu
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@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+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@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+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en