本当はmethodnameに相当するkeywordを作ってマップで返したかったのですが、symbolからkeywordを作る手段が思いつかず、断念しました。
シンボルからキーワードは (keyword 'sym) で OK
元エントリのは単純なメソッドにしか使えないので、もうちょっと便利にしてみた (obj-values-3)
bean とか知らないので勘違いしている可能性アリ
マクロ定義
; 引数未対応版 (defmacro obj-values-2 "Takes a Java object and method names, returns a list of method values." [obj & names] (let [o (gensym) kvs (->> names (map #(list (keyword %) `(. ~o ~%))) (apply concat))] `(let [~o ~obj] (hash-map ~@kvs)))) ; 引数&メソッドチェイン対応版 (defmacro obj-values-3 "Takes a Java object and method names, returns a list of method values." [obj & names] (let [o (gensym) kvs (->> names (map #(if (sequential? %) (list (keyword (first %)) `(.. ~o ~@(rest %))) (list (keyword %) `(. ~o ~%)))) (apply concat))] `(let [~o ~obj] (hash-map ~@kvs))))
実行例
user=> (obj-values-2 (java.io.File. ".") toString hashCode canRead) {:toString ".", :canRead true, :hashCode 1234367} user=> (obj-values-3 (java.io.File. ".") canRead (can-read-str canRead toString) (eq (equals "hoge"))) {:eq false, :can-read-str "true", :canRead true}
つっこみ
([obj methodname & methodnames] `(concat (obj-values ~obj ~methodname) (obj-values ~obj ~@methodnames)))
この場合、obj が複数回評価されうるのでよろしくないと思います。
`(let [obj# ~obj] (concat (obj-values obj# ~methodname) (obj-values obj# ~@methodnames)))))
こんなんが良い、かも?