Skip to content

Instantly share code, notes, and snippets.

@zoldar
Last active December 29, 2015 09:39
Show Gist options
  • Save zoldar/7651739 to your computer and use it in GitHub Desktop.
Save zoldar/7651739 to your computer and use it in GitHub Desktop.
;; WARNING: the code here wasn't tested in REPL
(ns space-age)
(def earth-year-in-seconds 31557600.0)
(def orbital-periods
{:mercury 0.2408467
:venus 0.61519726
:mars 1.8808158
:jupiter 11.862615
:saturn 29.447498
:uranus 84.016846
:neptune 164.79132})
;; Instead of implicitly creating root bindings for functions I create a "factory" function.
(defn solar-age-calculation-for
"Returns a function which, when given an age in seconds, calculates age in given planet's solar years."
[planet]
(if-let [period (orbital-periods planet)]
(fn [seconds]
(/ seconds (* period earth-year-in-seconds)))
(throw (Exception. (str "Invalid planet " planet)))))
;; This way, I can easily extend the API with specialized functions for planets.
;; Yes, it's a couple more keystrokes to create these than generating them with
;; a macro, but the bindings are explicit and easily discoverable when going through
;; the code.
(def solar-age-on-mercury (solar-age-calculation-for :mercury))
;; If the space of possibilities would be too big to create all possible bindings
;; by hand, I would either use the factory function in contexts where there are
;; many values to be calculated for a given planet or use a generalized version:
(defn solar-age-on [planet period]
(partial solar-age-calculation-for planet))
;; The generalized function has additional benefit of allowing for calculation of the value
;; for multiple planets.
(defn solar-age-for-all-planets [seconds]
(into {} (map (juxt identity solar-age-on) (keys orbital-periods) (repeat seconds))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment