[racket-dev] dependent contracts: use them more!
[ 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