As I posted a couple weeks ago, I've been finding it awkward that Clojure doesn't have too many math functions that know how to "do the right thing" with the various numeric types it uses. The one that's been bothering me the most is the lack of an expt function. Calling Math/pow automatically coerces everything to doubles, which isn't necessarily the desired behavior.
So I took this as an opportunity to learn how Clojure's multimethods
work, and coded up a sample expt implementation, which I've attached
and pasted below. I'd like to hear some comments on whether I'm
utilizing multimethods correctly, and whether functions like this
would be beneficial for inclusion in the clojure contribs. If people
find this useful, there are a few other math functions which would
benefit from this sort of conversion as well.
(derive java.lang.Integer ::exact)
(derive java.lang.Integer ::integer)
(derive java.math.BigInteger ::exact)
(derive java.math.BigInteger ::integer)
(derive java.lang.Long ::exact)
(derive java.lang.Long ::integer)
(derive java.math.BigDecimal ::exact)
(derive clojure.lang.Ratio ::exact)
(derive java.lang.Double ::inexact)
(defmulti expt (fn [x y] [(class x) (class y)]))
(defn- expt-int [base pow]
(loop [n pow, y 1, z base]
(let [t (bit-and n 1), n (bit-shift-right n 1)]
(cond
(zero? t) (recur n y (* z z))
(zero? n) (* z y)
:else (recur n (* z y) (* z z))))))
(defmethod expt [::exact ::integer] [base pow]
(cond
(pos? pow) (expt-int base pow)
(zero? pow) 1
:else (/ 1 (expt-int base (- pow)))))
(defmethod expt :default [base pow] (Math/pow base pow))
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to [email protected]
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
-~----------~----~----~----~------~----~------~--~---
expt.clj
Description: Binary data
