Adding Live Unit Feeds to Frinj
clojure frinjA couple of weeks have passed since I pushed Frinj to github and blogged/tweeted about it. The response has been pretty awesome, one highlight being when @stuarthalloway showed me a frinj+datomic example gist on the #datomic IRC channel. In short, the Clojure community is #badass.
Frinj comes with a big database of units and conversion factors, and while many conversion factors are “eternal”, others aren’t. Exchange rates, for instance, have to be kept up to date to be relevant. The Frinj unit database was designed to be updatable, both for usability when doing various calculations and for rates that constantly change. This is the reason the frinj.calc namespace exposes the (frinj-init!) function to reset the unit database to a known baseline (in case you write over some factors, etc.). Clojure’s support for atomically updating state is ideal for this purpose; the calculator’s state is kept in a number of refs and, thanks to the STM, always kept consistent.
Frinj now supports live currency exchange rates, precious/industrial metals and agrarian commodities, by adding the concept of unit feeds. This is handled by the new frinj.feeds namespace, and the basic idea is to have multiple feeds sharing one ScheduledThreadPoolExecutor for periodically updating Frinj’s state. The generic feed utility functions; (start-feed, stop-feed, update-units!) are separated from the feed specific ones. For more information see the wiki and source. As you can imagine, these live units rates are just a couple of many potential feeds.
Currencies use the 3 letter (ISO 4217) currency acronym (uppercase), and the metals and commodities use capitalised names, see below for examples.
I’ve also added an new convenience namespace called frinj.repl that will initialise the built-in units, start the feeds and immigrate the rest of the frinj vars.
user=> (use 'frinj.repl)
user=> (str (fj 10 :thousand :SEK :to :GBP)) ;; standard currency conversion
"937.1075201531269 [dimensionless]"
user=> (str (fj :Gold :per :Silver)) ;; Gold vs Silver price
"49.95612708018155 [dimensionless]"
user=> (str (fj :Milk))
"0.3659673552268969 dollar kg^-1 [price_per_mass]"
Next time, I’ll explain how to use Frinj in ClojureScript.