Trammel – Contracts Programming for Clojure
Trammel
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:
- Abstracting out the use of
partial
(in progress) - Better error messages
- Distinct pre and post exceptions
- An all-in-one defn/contract (in progress)
- Study the heck out of everything Bertrand Meyer ever wrote (in progress)
- Choose better names than
requires
andensures
- Facilities for slackening
requires
and tighteningensures
(in progress)
If you have any ideas or interesting references then I would be happy to discuss.
:f
5 Comments, Comment or Ping
David Cabana
You mentioned Eiffel and asked for interesting references… Be sure to check out Bertrand Meyer’s magnum opus, “Object Oriented Software Construction”. The book is highly opinionated and very interesting, even if you have no intention of ever writing a line of Eiffel. Plenty of material on contracts if I recall correctly.
Here’s the Amazon link: http://www.amazon.com/Object-Oriented-Software-Construction-Book-CD-ROM/dp/0136291554/ref=sr_1_1?ie=UTF8&s=books&qid=1274870804&sr=8-1
May 26th, 2010
fogus
I read that many years ago and still have it packed away if I recall. It will be found. Thank you. :-)
May 26th, 2010
jrandom
If you’re looking to abstract away the “partial” part with the contract application, perhaps you should make a pair of macros “with-contracts” and “defn-requiring”?
May 26th, 2010
Konrad Hinsen
I wonder in which situation it is useful to separate a contract from the function that fulfills that contract. I rarely have several function that all satisty the same contract, so there would be no reuse at all. The main exception would be multimethods or protocol functions for which all implementations share the same contract. But then I’d want a construct that attaches the contract to a protocol or a multimethod, rather than one that defines the contract separately, making me apply it explicitly to each implementation.
May 27th, 2010
fogus
Agreed. This is item #4 (no priority ordering implied) and is in progress.
May 27th, 2010
Reply to “Trammel – Contracts Programming for Clojure”