Skip to content

Instantly share code, notes, and snippets.

@alandipert
Created June 28, 2012 03:45
Show Gist options
  • Select an option

  • Save alandipert/3008852 to your computer and use it in GitHub Desktop.

Select an option

Save alandipert/3008852 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
@alandipert
Copy link
Author

This has been rolled into a library called mathemagician.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment