How do I get the property of an object with a variable property name?

#1

If I want to access a property called transform I could do it this way:

(. obj transform)

But what if I have a variable and want to access a property with the same name as the value of the variable:

(let [prop 'transform] (. obj prop))

This obviously doesn’t work, but how do I make it work? I tried doing things like:

(eval `(. ~'obj ~prop))

But eval won’t help me since prop is lexically bound.

Is there just a function version of . lying around?

#2

Maybe something like this?

(defmacro call-by-string [obj prop]
  `(. ~obj ~(symbol prop)))

so you can do:

(call-by-string "foo" "length") ;;=> 3
#3

Sadly this won’t work, since if you put a variable rather than a value in the second parameter, it will break:

(let [prop "length"] (call-by-string "foo" prop))
;;=> ... Cannot find instance field/property/member name prop

And this is how it looks if you macroexpand:

(let [prop "length"]
  (macroexpand '(call-by-string "foo" prop)))
;;=> (. "foo" prop)
#4

This also works, but it uses reflection:

(clojure.lang.Reflector/invokeInstanceMethod "foo" "length" (into-array [])) ;;=> 3
2 Likes
#5

Thanks bork, reflection is perfectly fine in this case. :slight_smile: It was something like this I was looking for. I’ll try it out soon.

EDIT: Worked perfectly, thanks. :slight_smile: