What it is
----------

Trammel is a [Clojure](http://clojure.org) providing contracts programming 
(sometimes called "[Design by 
Contract](http://en.wikipedia.org/wiki/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](http://www.eiffel.com/) and [Racket 
Scheme](http://docs.racket-lang.org/reference/contracts.html).

Absorb
------

You can use Trammel in your 
[Leiningen](https://github.com/technomancy/leiningen) and 
[Cake](https://github.com/flatland/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](https://github.com/fogus/trammel)
* [Ticket system](https://github.com/fogus/trammel/issues)
* [Examples and documentation](http://fogus.github.com/trammel/) -- in 
progress
* [Dream Date](http://github.com/fogus/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.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to