Trammel version 0.7.0 (reference invariants++)
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.
Absorb
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:
<dependency>
<groupId>org.clojure</groupId>
<artifactId>trammel</artifactId>
<version>0.7.0</version>
</dependency>
Enjoy!
Places
- Source code
- Ticket system
- Examples and documentation — in progress
- Dream Date – an example project using Trammel — in progress
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
Atoms are created directly with their invariants:
(def a (constrained-atom 0
"only numbers allowed"
[number?]))
@a
;=> 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
Refs are created directly with their invariants:
(def r (constrained-ref 0
"only numbers allowed"
[number?]))
And also checked on change, within a transaction:
(dosync (alter r inc))
;=> 1
(dosync (alter r str))
; Pre-condition failure: only numbers allowed
Vars
Vars are created directly with their invariants:
(defconstrainedvar ^:dynamic foo 0
"only numbers allowed in Var foo"
[number?])
Var invariants are checked on rebinding, such as with binding
:
(binding [foo :a] [foo])
; Pre-condition failure: only numbers allowed
Agents
Agents are created directly with their invariants:
(def ag (constrained-agent 0
"only numbers allowed"
[number?]))
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.
Plans
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
Caspar Hasenclever
Interesting lib!
Did you mean “You can use trammel” instead of “You can use core.cache” in the first sentence in “Absorb”?
Cheers,
Caspar
Apr 6th, 2012
Sam Tobin-Hochstadt
We just call it Racket, no “Scheme” required.
Apr 6th, 2012
Reply to “Trammel version 0.7.0 (reference invariants++)”