Update
This question is largely a duplicate, but both the question and my answer below seem more expository. See Access Java fields dynamically in Clojure? for the previous question.
I am trying to look up the settings of fields in instances of Java objects from Clojure. The dot operator seems to fail in places where I would naively expect it to work.
For example, with these definitions in place...
(defn example-point []
(let [instance (java.awt.Point. 1 2)]
(list (. instance x) (. instance y))))
(defn example-point-1 []
(let [instance (java.awt.Point. 1 2)
fields '("x" "y")]
(map #(. instance (symbol %))
fields)))
(defn example-point-2 []
(let [instance (java.awt.Point. 1 2)
fields (map symbol '("x" "y"))]
(map (fn [field] (eval `(. ~instance ~field)))
fields)))
I get these return values:
flood.core> (example-point)
(1 2)
That's great, but what if I want to supply the name of the field "programmatically"? That's what the other functions are supposed to do. To my naive way of thinking, they should return the same value as above. But they both give different errors.
flood.core> (example-point-1)
IllegalArgumentException No matching method found: symbol for class java.awt.Point clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:53)
flood.core> (example-point-2)
CompilerException java.lang.RuntimeException: Can't embed object in code, maybe print-dup not defined: java.awt.Point[x=1,y=2], compiling:(/tmp/form-init1213427540543573506.clj:1:5659)
I'm stuck, can you help me figure this out?
Further update
I did try this, and it produces yet another error.
;; added in response to suggestion...
(defn example-point-3 []
(let [instance (java.awt.Point. 1 2)
fields (map symbol '("x" "y"))]
(map (fn [field] (eval `(. instance ~field)))
fields)))
flood.core> (example-point-3)
CompilerException java.lang.RuntimeException: No such var: flood.core/instance, compiling:(/tmp/form-init1213427540543573506.clj:1:5659)