read


read
or learn more

Trammel – Contracts Programming for Clojure

May 25, 2010

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:

  1. Abstracting out the use of partial (in progress)
  2. Better error messages
  3. Distinct pre and post exceptions
  4. An all-in-one defn/contract (in progress)
  5. Study the heck out of everything Bertrand Meyer ever wrote (in progress)
  6. Choose better names than requires and ensures
  7. Facilities for slackening requires and tightening ensures (in progress)

If you have any ideas or interesting references then I would be happy to discuss.

:f

5 Comments, Comment or Ping

  1. 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

  2. I read that many years ago and still have it packed away if I recall. It will be found. Thank you. :-)

  3. 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”?

  4. 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.

  5. But then I’d want a construct that attaches the contract to a protocol or a multimethod

    Agreed. This is item #4 (no priority ordering implied) and is in progress.

Reply to “Trammel – Contracts Programming for Clojure”