Hi, I've been working on some Java libraries wrappers lately and came up with patterns on how to clojurize them. I'm wondering if you guys got other such patterns?
Here's what I came up with: (import 'java.lang.reflect.Modifier) (defn clojurize-name [name] (apply str (interpose "-" (map #(.toLowerCase %) (re-seq #"\w[a-z]+" name))))) (defn clojurize-constant-name [name] (.replace (.toLowerCase (str name)) "_" "-")) (defn enum->map [names constants] (into {} (map #(vector (keyword (clojurize-constant-name %1)) %2) names constants))) (defn get-static-fields [klass] (filter #(Modifier/isStatic (.getModifiers %)) (.getFields klass))) (defn wrap-enum [klass] (if (isa? klass Enum) (let [cs (.getEnumConstants klass)] (enum->map (map str cs) cs)) (let [cs (get-static-fields klass)] (enum->map (map #(.getName %) cs) (map #(.get % nil) cs))))) (defn call-method [name obj & args] (apply list (symbol (str "." name)) obj args)) (defmacro wrap-methods-into [obj klass & [flter rename]] (let [methods (filter (eval flter) (.getDeclaredMethods (resolve klass)))] (reduce #(into %1 (let [name (.getName %2)] {((eval rename) name) (call-method name obj)})) {} methods))) (defn getter? [method] (and (= 0 (count (.getParameterTypes method))) (re-seq #"get[A-Z$]" (.getName method)))) (defmacro wrap-getters-with [obj klass] `(wrap-methods-into ~obj ~klass getter? (comp keyword (fn [s#] (.replace s# "get-" "")) clojurize-name))) I use this code mainly to write a Java Sound API wrapper, here's some examples: (def float-controls (wrap-enum javax.sound.sampled.FloatControl$Type)) user> (pprint float-controls) {:balance #<Type Balance>, :reverb-return #<Type Reverb Return>, :master-gain #<Type Master Gain>, :aux-return #<Type AUX Return>, :pan #<Type Pan>, :reverb-send #<Type Reverb Send>, :sample-rate #<Type Sample Rate>, :aux-send #<Type AUX Send>, :volume #<Type Volume>} and... (defn format-info [audio-format] (into (wrap-getters-with audio-format javax.sound.sampled.AudioFormat) {:endianness (if (.isBigEndian audio-format) :big-endian :little-endian)})) user> (pprint (-> "g:/test.mp3" ->stream ->format format-info)) {:channels 2, :frame-rate 38.28125, :frame-size -1, :sample-rate 44100.0, :sample-size-in-bits -1, :encoding #<MpegEncoding MPEG1L3>, :endianness :big-endian} I'm still not sure about how to properly name the macros, if anybody got a better idea, I sure want to ear it. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@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+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en