Skip to content

Instantly share code, notes, and snippets.

@fogus
Forked from alandipert/automath.clj
Created June 29, 2012 02:06
Show Gist options
  • Save fogus/3015222 to your computer and use it in GitHub Desktop.
Save fogus/3015222 to your computer and use it in GitHub Desktop.
Namespace of functions that are proxies for methods on java.lang.Math for maximum developer convenience.
(ns automath
"Namespace of functions that are proxies for methods on
java.lang.Math for maximum developer convenience."
(:use [clojure.string :only (lower-case)]))
(def ^{:private true
:doc "Set of method names not to generate a proxy function for."}
exclusions #{"min" "max"})
(defn- methods-in
"Returns a map of method names to Methods implemented in klass."
[klass]
(filter (comp #{klass} #(.getDeclaringClass %)) (.getMethods klass)))
(defn- names-arities
"Given a collection of methods, returns a map of method names to sets of arities."
[methods]
(reduce (fn [sigs meth]
(update-in sigs
[(.getName meth)]
(fnil conj #{})
(count (.getParameterTypes meth))))
{}
methods))
(defn- clojurize
[s]
(->> s
(map #(if (Character/isUpperCase %) (str "-" %) %))
(apply str)
lower-case))
(defn- fn-impls
"Returns a list of function implementations corresponding to all
methods and their arities on klass, excluding any methods in
exclude-names."
[exclude-names klass]
(for [[name arities] (names-arities (methods-in klass))
:when (not (exclude-names name))]
(let [args (map #(vec (take % (repeatedly gensym))) arities)
clj-name (clojurize name)]
`(defn ~(symbol clj-name)
~@(map (fn [argv] (list argv (list* '. klass (symbol name) argv)))
args)))))
(defn- install-fns
"Generates proxy functions for klass and installs them in this namespace."
[klass]
(eval (cons 'do (fn-impls exclusions klass))))
(install-fns Math)
;;; Before:
;;; (Math/abs -4) ;=> 4
;;; (Math/floor 2.3) ;=> 2.0
;;; Now:
;;; (use 'automath)
;;; (abs -4) ;=> 4
;;; (floor 2.3) ;=> 2.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment