[racket-dev] dependent contracts: use them more!

From: Robby Findler (robby at eecs.northwestern.edu)
Date: Thu Sep 9 15:32:37 EDT 2010

[ Exec summary: dependent contracts aren't slow anymore, so use them more! ]

There are not many uses of dependent contracts in our git respository
or in planet. I have a sense that people avoid dependent contracts
because they are slow. While ->d is remarkably slow, I'm not sure how
widespread this impression is or if it really is a reason but I've
gone ahead and improved dependent contract's performance with a new
contract combinator, ->i (this guy is motivated by Christos Dimoulas's
research so is different from ->d in how it deals with contracts that
"break themselves" but I'll leave that story for another time).

Performance-wise, the main difference between ->d and ->i is that you
have to be more explicit about the dependencies between arguments with
->i contracts. Specifically, if one argument depends on another one,
then you have to list that. For example, in this contract:

  (->i ([x (y) (<=/c y)] [y integer?]) [res integer?])

The contract on x depends on the value of y, and the list of variables
"(y)" in the clause for the x argument indicates that. Also, since y
does not depend on the values of the function arguments, then it has
no list at all. This is the corresponding ->d contract, where such
lists are not part of the syntax:

  (->d ([x (<=/c x)] [y integer?]) [res integer?])

The ->i contract runs 12x faster than the ->d one (when checking the
function (lambda (x y) (+ x y))).

Even better, the ->i contract above runs within an epsilon of the time
that the contract (-> integer? integer? integer?) runs, for the same
example.

So, please do try using dependent contracts more!

Robby


Posted on the dev mailing list.