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?
--
Petr Gladkikh
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?
--
Petr Gladkikh
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 clo...@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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
--
And what is good, Phaedrus,
And what is not good—
Need we ask anyone to tell us these things?
I tried this since I have not used macroses for real problem so far.
And it actually works.
But I do not understand why it works.
I have class:
class Foo {
public String s;
public int v;
public String toString() { return "{" + s + "," + v + "}"; }
}
Then in Clojure:
(defsetter abcde [:s :v])
(let [afoo (actialpackage.Foo.)]
(set-abcde afoo {:s "S" :v 42})
(println afoo))
But at the moment (defsetter abcde [:s :v]) is expanded nothing is
known about actual class.
So it is not clear to me why this works but giving field names at
runtime does not.
Can anyone clarify this?
Maybe this wokrs because in this case compiler can infer type of java
object at compile time?
--
Petr Gladkikh
The macro expands into field-accessing code. If the compiler infers
the type, this becomes fast bytecode to access the fields. Otherwise
it becomes slowish reflection calls, but still works.