Skip to content

Instantly share code, notes, and snippets.

@christoph-frick
Created March 6, 2017 20:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save christoph-frick/45ba5bb7fe96665acf967f87cfd9af4d to your computer and use it in GitHub Desktop.
Save christoph-frick/45ba5bb7fe96665acf967f87cfd9af4d to your computer and use it in GitHub Desktop.
Experiment about using reflection in macros for #clojure
(require '[clojure.reflect :refer [type-reflect]])
(require '[clojure.walk :refer [postwalk]])
(require '[clojure.set :refer [subset?]])
(defn public-static? [{:keys [flags]}]
(subset? #{:public :static} flags))
(def public-static-member?
(memoize
(fn public-static-member? [cls sym]
(let [members (:members (type-reflect cls))]
(some (fn [{name :name :as member}]
(and (public-static? member) (= sym name)))
members)))))
#_ (public-static-member? String 'blerg)
#_ (public-static-member? String 'valueOf)
#_ (public-static-member? Long 'MEDIUM_VALUE)
#_ (public-static-member? Long 'MAX_VALUE)
(defmacro foo [cls form]
(postwalk
(fn [x]
(if (and (seq? x) ((every-pred symbol? (partial public-static-member? cls)) (first x)))
`(. ~cls ~@x)
x))
form))
#_ (foo java.lang.String (= "1" (valueOf 1)))
#_ (foo java.lang.String (= "6" (valueOf (+ 1 2 3))))
#_ (foo java.lang.String (= "123" (apply str (map #(valueOf %) [1 2 3]))))
#_ (foo java.lang.Long (MAX_VALUE))
;; from amalloy in irc -- might contain quoting errors. macrolet is from https://github.com/clojure/tools.macro
#_ (defmacro foo [cls & body] `(macrolet [~@(for [{:keys [name flags] (:members (type-reflect cls)) :when (public-static? flags)}] `(~name [& args#] `(. ~~cls ~~name ~@args#)))] ~@body))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment