Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Contracts programming with Clojure

branch: prepost

This branch is 0 commits ahead and 69 commits behind master

Fetching latest commit…

Cannot retrieve the latest commit at this time

README.md

Trammel

Contracts programming for Clojure.

Example

Function Contracts

(use '[fogus.me.trammel :only [provide-contracts]])

(defn sqr [n] (* n n))

(sqr 10)
;=> 100
(sqr 0)
;=> 0

(provide-contracts 
  [sqr "Constraints for squaring" 
    [x] [number? (not= 0 x) => number? pos?]])

(sqr 10)
;=> 100
(sqr 0)
; java.lang.AssertionError: Assert failed: (not= 0 x)

Record Invariants

(use 'fogus.me.trammel)

(defconstrainedrecord Foo [a 1 b 2]
  [(every? number? [a b])]
  Object
  (toString [this] (str "record Foo has " a " and " b)))

;; default ctor with default values
(new-Foo)
;=> #:user.Foo{:a 1, :b 2}

;; kwarg ctor
(new-Foo :a 42)
;=> #:user.Foo{:a 42, :b 2}

;; use like any other map/record
(assoc (new-Foo) :a 88 :c "foo")
;=> #:user.Foo{:a 88, :b 2, :c "foo"}

;; invariants on records checked at runtime    
(assoc (new-Foo) :a "foo")
; Assert failed: (every? number? [a b])

Getting

Leiningen

Modify your Leiningen dependencies to include Trammel:

:dependencies [[trammel "0.4.6"] ...]    

Maven

Add the following to your pom.xml file:

<dependency>
  <groupId>trammel</groupId>
  <artifactId>trammel</artifactId>
  <version>0.4.6</version>
</dependency>

Notes

Trammel is in its infancy but I think that I have a nice springboard for experimentation and expansion, including:

  • Better error messages
  • Distinct pre and post exceptions
  • Study the heck out of everything Bertrand Meyer ever wrote (in progress)
  • defconstraint -- with ability to relax requires and tighten ensures
  • Study the heck out of Racket Scheme (in progress)
  • Modify macros to also allow regular Clojure constraint maps
  • Reference contracts
  • Make the anything constraint cheap (elimination)
  • Allow other stand-alones: true/false, numbers, characters, regexes
  • Make provide-contracts more amenable to REPL use
  • Generate a Foo? function (in progress)

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

References

Emacs

Add the following to your .emacs file for better Trammel formatting:

(eval-after-load 'clojure-mode
  '(define-clojure-indent
     (contract 'defun)
     (defconstrainedfn 'defun)
     (defcontract 'defun)
     (provide 'defun)))
Something went wrong with that request. Please try again.