Hello all, below is the code for an utility macro. It wraps all public static functions of a class in closure functions and imports them into the current namespace. Clojure name will be prefix-'method name'.
Example: (import-static \"foo\" java.lang.Math) And yes, I saw static import from contrib :) - the difference here is that my code creates clojure functions that can be passed to other functions. This is just an exercise for learning clojure macros, so I would be very grateful for any comments on the code, suggestions on how to improve it, etc ... It is easier to read from bottom and up ... I have not implemented multimethod support yet, so currently only the first of overloaded methods will be imported. Thank you for your help, Boris ------------------------------------------ ;;; some utility funcitons (defn mk-counter "returns a function that for each returns a successive integer for each invocation." ([] (mk-counter 0)) ([start] (let [n (atom start)] (fn [] (- (swap! n inc) 1))))) (defn seq-to-multimap "takes a sequence s of possibly repeating elements and converts it to a map, where keys are obtained by applying key-fn to elements of s and values are sequences of all elements of s with a given key" [s key-fn] (reduce (fn [m el] (let [key (key-fn el)] (assoc m key (conj (m key []) el)))) {} s)) ;;; static import helper functions (def primitive-type-translation { "bool" "Boolean" "char" "Character" "long" "Long" "int" "Integer" "short" "Short" "byte" "Byte" "float" "Float" "double" "Double"}) (defn resolve-primitive-type [#^String t] (primitive-type-translation t t)) (defn type-2-symbol "resolves type name into a symbol, converts primitive types to boxed types" [type] (symbol (resolve-primitive-type (.getCanonicalName type)))) (defn get-ps-methods "returns all public static methods of a class c" [c] (let [methods (.getMethods c)] (filter #(let [mod (.getModifiers %1)] (and (java.lang.reflect.Modifier/isStatic mod) (java.lang.reflect.Modifier/isPublic mod))) methods))) (defn get-methods-multimap "returns a multimap of publi static methods of a class c" [c] (seq-to-multimap (get-ps-methods c) #(.getName %1))) (defn make-java-method-symbol "returns a symbol that corresponds to a fully qualified name of the java method" [#^java.lang.reflect.Method method] (symbol (str (.. method getDeclaringClass getName) "/" (.getName method)))) (defn get-method-args "returns a java Class[] array of method's argument types" [method] (.getParameterTypes method)) (defn mk-param [param count] "returns clojure expression for the parameter declaration with the type" (with-meta (symbol (str "param" count)) {:tag (type-2-symbol param)})) (defn mk-params-list [method] "returns clojure expression for the parameter declarations of a funciton" (let [c (mk-counter 0)] (into [] (map #(mk-param %1 (c)) (get-method-args method))))) (defn mk-call-exp [method] "returns clojure expression for the function call. Example: (java.lang.Math/min param0 param1) " (let [c (mk-counter 0)] (cons (make-java-method-symbol method) (map (fn [param] (symbol (str "param" (c)))) (get-method-args method))))) (defn mk-func-name [prefix method] (symbol (str prefix "-" (.getName method)))) (defn mk-func-def [prefix method] `(defn ~(mk-func-name prefix method) ~(mk-params-list method) ~(mk-call-exp method))) ;;; the macro itself (defmacro import-static "wraps all public static functions of a class in closure functions and imports them into the current namespace. Clojure name will be prefix-'method name'. Example: (import-static \"foo\" java.lang.Math) TODO: multimethod support, currently only the first of overloaded methods will be imported. " [prefix class] `(do ~@(map (fn [[name [method & rest]]] (mk-func-def prefix method)) (get-methods-multimap (. Class forName (str class)))))) ---------------------------------------------------------------- --~--~---------~--~----~------------~-------~--~----~ 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 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 -~----------~----~----~----~------~----~------~--~---