I was planning on making a grand announcement about the launch of my Clojure contracts programming library Trammel, but got totally upstaged by something called Clojure/core. ^_^
While researching for The Joy of
Clojure I eventually came by a few books about the Eiffel Programming
Language and was blown away by its notion of design
by contract©. I’ve posted before about Clojure’s pre- and
post-conditions but didn’t take it to the next step until chapter 7
of JoC – which forms the basis for Trammel. At the moment I have only
the base form contract
returning a higher-order function
that can then be partially applied to an existing function to “apply” a
contract:
(def cheese-contract
(contract cheese
[x]
(requires
(= x :cheese))
(ensures
(string? %)
(= % "cheese"))
[x y]
(requires
(every? #(= :cheese %) [x y]))
(ensures
(string? %))))
(def do-something
(partial
cheese-contract
(fn
([x] (name x))
([x y] (str x y)))))
(do-something :cheese)
;=> "cheese"
(do-something :foo)
; java.lang.AssertionError: Assert failed: (= x :cheese)
(do-something :cheese :cheese)
;=> ":cheese:cheese"
(do-something :cheese :ham)
; java.lang.AssertionError: Assert failed:
; (every? (fn* [p1__6079#] (= :cheese p1__6079#)) [x y])
Anyway, Trammel is in its infancy but I think that I have a nice springboard for experimentation and expansion, including:
partial
(in progress)requires
and
ensures
requires
and tightening
ensures
(in progress)If you have any ideas or interesting references then I would be happy to discuss.
:f