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