A Clojure library for units of measurement.
Few languages have built-in support for numerical quantities in a system of units. This library brings Clojure into the world of unit-aware computing; in fact, it abstracts away as much of the unit bookkeeping as possible in a functional, lispy way.
The aims of units2
are to be highly expressive, unintrusive, and easy to use. The salient points of units2
are:
map
, comp
, etc.+
,-
,*
,/
,==
, etc.), accessible
This library also respects the distinction between the algebra on quantities with units and the algebra on units themselves. This is an important prerequisite for dimensional analysis, nonlinear unit conversions (e.g. celsius-fahrenheit), and automatic 'unitification' of custom arithmetic operations and/or numerical differentiation and integration schemes.
There's a tutorial to help get started with the library, and some example code in spice.clj
. There's also a summary of the API (more of a cheatsheet really). Some effort was put into writing readable, well-commented code, but if you're impatient, here's the executive summary:
;; core utilities, a collection of units and math ops
(require '[units2.core :refer :all])
(require '[units2.stdlib :refer :all])
(require '[units2.ops :as ops])
;; a function that computes an average, no matter what the units are
(ops/with-unit-arithmetic
(defn average [numlist]
(/ (apply + numlist) (count numlist))))
;; sec (second), minute, hour are units from the stdlib.
(def self-reported-half-marathon-times
{:Bob (hour 3.5)
:Claire (minute 203)
:JJ (ops/+ (minute 64) (sec 52)) ;; April 2017 world record
:Chuck-Norris (hour -3) ;; The finish line ran towards him
})
;; compute average and return the result (in units of hours)
((comp hour average vals) self-reported-half-marathon-times) ; --> 1.24 hours
;; Wait a minute... let's exclude Chuck Norris from the average
(Thread/sleep (getValue (minute 1) msec)) ; literally wait one minute
(let [realistic (fn [x] (filter #(ops/> % (minute 0)) x))]
((comp hour average realistic vals)
self-reported-half-marathon-times)) ; --> 2.65 hours
;; 2.65 hours still hard to read because our clocks use sexagesimals.
;; Let's split this into hours and minutes (by hand, just for illustration)
((juxt ops/quot (comp minute ops/rem))
(hour 2.65) (hour 1) (hour 1)) ; --> [(hour 2.0) (minute 39)]
No Clojure library is complete without a bit of etymology.
Unit is an alteration of unity, from Old French unite ("uniqueness, oneness", c. 1200), from the Latin unitas (cf. below), itself derived from unus ("one"). Unit was popularized by the English commented translation of Euclid's Elements (J. Dee and H. Billingsey, 1570), to express the Greek monos ("unique, solitary").
Extended sense of "a quantity adopted as a standard of measure" is from 1738 (!).
Originally unitas, unitatis, (f), "oneness, sameness, agreement". More explicitly:
(The material above was adapted from etymonline.com; claim (!) has not been independently verified.)
Can you improve this documentation? These fine people already did:
mfey, Michael Feyereisen & Michael R FeyereisenEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close