or learn more

Trammel version 0.7.0 (reference invariants++)

Apr 6, 2012

Trammel is a Clojure providing contracts programming (sometimes called “Design by Contract” or DbC) capabilities. Features of Trammel currently include:

  • Contracts on functions
  • Composable contracts
  • Post-definition function contract application
  • defrecord and deftype invariants
  • Reference type invariants (i.e. Agents, Atoms, Refs, and Vars)
  • Ability to turn-off checks in a production setting
  • Support for Clojure versions 1.3 and 1.4

Trammel is inspired by Eiffel and Racket.


You can use Trammel in your Leiningen and Cake projects with the following :dependencies directive in your project.clj file:

    [trammel "0.7.0]

For Maven-driven projects, use the following slice of XML in your pom.xml‘s <dependencies> section:




Changes from version 0.6.0

  • Better assertion error reporting
  • Ability to add constraint descriptions used in assertion reporting
  • Constrained defrecords no longer support default field values
  • Constrained defrecords no longer generate keyword args ctor function
  • Reference type invariants

Reference type invariants work in the following ways.


Atoms are created directly with their invariants:

(def a (constrained-atom 0
         "only numbers allowed"

;=> 0

And checked on change:

(swap! a inc)
;=> 1

Invariant violations are reported right away:

(swap! a str)
; Pre-condition failure: only numbers allowed 

(compare-and-set! a 0 "a")
; Pre-condition failure: only numbers allowed 


Refs are created directly with their invariants:

(def r (constrained-ref 0
         "only numbers allowed"

And also checked on change, within a transaction:

(dosync (alter r inc))
;=> 1

(dosync (alter r str))
; Pre-condition failure: only numbers allowed 


Vars are created directly with their invariants:

(defconstrainedvar ^:dynamic foo 0
  "only numbers allowed in Var foo"

Var invariants are checked on rebinding, such as with binding:

(binding [foo :a] [foo])
; Pre-condition failure: only numbers allowed 


Agents are created directly with their invariants:

(def ag (constrained-agent 0
         "only numbers allowed"

And are checked on send and send-off

(send ag str)
(agent-error ag)

However, the invariant violations are reported consistently with the agent setup. In this case, the errors are accessible via the agent-error function.


The following capabilities are under design, development, or consideration for future versions of Trammel:

  • Contracts for higher-order functions
  • Better error messages
  • defconstraint — with ability to relax requires and tighten ensures
  • Modify macros to also allow regular Clojure constraint maps
  • Allow other stand-alones: true/false, numbers, characters, regexes
  • Marrying test.generative with Trammel
  • More documentation and examples

More planning is needed around capabilities not listed nor thought of.

2 Comments, Comment or Ping

  1. Caspar Hasenclever

    Interesting lib!

    Did you mean “You can use trammel” instead of “You can use core.cache” in the first sentence in “Absorb”?



  2. Sam Tobin-Hochstadt

    We just call it Racket, no “Scheme” required.

Reply to “Trammel version 0.7.0 (reference invariants++)”