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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en