On Tue, Jul 26, 2011 at 6:02 AM, Petr Gladkikh <petrg...@gmail.com> wrote:
> On Tue, Jul 26, 2011 at 3:28 PM, Alan Malloy <a...@malloys.org> wrote:
>> On Jul 25, 11:10 pm, Petr Gladkikh <petrg...@gmail.com> wrote:
>>> I am trying to construct java object and assign it's fields from a map.
>>> That is given Java object of class Something { long id; String name; }
>>> and Clojure map {:id 12, :name "Impostor"}
>>> I would like to set fields of java object to respective values from map.
>>>
>>> Now, this works
>>> (let [o (Something.)]
>>>   (set! (. o :id) 12)
>>>   (set! (. o :name) "Impostor")
>>>   o)
>>>
>>> But as soon as I use some value to get field expression compiler
>>> starts complaining "Invalid assignment target".
>>> that is
>>> (let [o (Something.)
>>>        ff :id]
>>>   (set! (. o ff) 12)
>>>   o)
>>> I do not understand why this problem occurs. Any variations that I
>>> tried to made it work do not do the trick.
>>> Including weird (or ridiculous) ones like (set! (. o (symbol (str ":"
>>> (name ff))) 12)
>>>
>>> I suspect that this has something to do with compiler that needs field
>>> names at compile time but Clojure could use reflection for this...
>>>
>>> Can anyone point to what is wrong here?
>>>
>>> By the way is there already some function that allows to set fields of
>>> an object from a map?
>>
>> Clojure *could* use reflection to do this...unless your object had a
>> field named ff! It has to decide at compile time how to look up a
>> field, and at that time it doesn't know your object won't have a .ff
>> field, so it figures, sure, I'll set the ff field.
>>
>> If you really want to do this (hint: you don't), you can manually deal
>> with the reflection that the compiler would generate, as Shantanu
>> outlines.
>
> Could you elaborate on this? What would you use instead in this case?
> My motivation is need to construct list of Java objects and I would
> like to have some concise syntax to write them. So I decided to do
> this with maps.
> I wrote a function that acts as constructor. But long list of
>
> (set! (. obj :aa) (:aa props))
> (set! (. obj :bb) (:bb props))
> (set! (. obj :cc) (:cc props))
> (set! (. obj :dd) (:dd props))
>
> looks not very lispy. Maybe I should use macros instead?

Untested! But should give a general idea how to do this sort of thing:

(defmacro defsetter [class keys]
  (let [o (gensym)
        p (gensym)]
    `(defn ~(symbol (str "set-" (.toLowercase (str class))))
       [~o ~p]
       ~@(map
           (fn [k]
             `(set! (. ~o ~k) (~k ~p)))
           keys))))

(defsetter Foo [:a :b])

(set-foo a-foo {:a 0 :b 42})

(defsetter Bar [:x :y :z])

(ser-bar a-bar {:x 4 :y 8 :z 15})

-- 
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.

-- 
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

Reply via email to