[plt-scheme] Contracts

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Wed Jul 12 08:50:31 EDT 2006

You could try this, too:

(module foo mzscheme
   (require (lib "contract.ss"))

   (define (f x) x)

   (provide/contract [f (-> positive? positive?)])
   (provide (rename f f:w/o-contract)))

(require foo)

;; ---

Here is another way to look at our contract philosophy. A Dyn Typ Lan  
allows programmers to superimpose their own "reasoning system" on  
values and functions, tailored to the situation. Often the "rules"  
include implication (speak subtyping), quantification (speak  
polymorphism), set subtraction (predicate dispatch), and so on.  
Granted a single programmer is omniscient and doesn't need to spell  
out the rules about his code. Problem is that this programmer can't  
write all the code in the world and must therefore glue his code to  
the code of other people. Clearly those other people aren't  
omniscient and so, well, you know what happens. They didn't use the  
rules in his spirit, they mess up, they introduce bugs, there are  
just no polite ways to describe these people.

So, for this reason, contracts are placed at boundaries. They can  
blame the "other" module when they fail. And presumably crossing the  
boundary happens much less often then staying within the box. The  
cost is not negligible but it's worth paying because contracts ensure  
that you don't get blamed for failures. It's always going to be the  
other guy's fault.

-- Matthias





On Jul 12, 2006, at 5:49 AM, Matt Jadud wrote:

> I've never really used the contract system; however, I figure Robby  
> and others have probably spent a lot of time making them work, so I  
> should consider using them. That, and my code might be safer/more  
> robust/self-documenting/colorfast in hot water.
>
> Although this is just an example, the first function I happened try  
> and write a contract for was recursive. It wasn't 'fact', but  
> that's OK.
>
> (define/contract fact
>     (number? . -> . number?)
>     (lambda (n)
>       (if (zero? n)
>           1
>           (* n (fact (sub1 n))))))
>
> This dies. I skimmed a tech report by Robby and Matthias re: HO  
> contracts, and see why this is problematic.
>
> This, of course, works:
>
> (module just-the-facts mzscheme
>   (require (lib "contract.ss"))
>   (provide/contract (fact (-> number? number?)))
>
>   (define (fact n)
>     (if (zero? n)
>         1
>         (* n (fact (sub1 n))))))
>
> Welcome to DrScheme, version 350.
> Language: Textual (MzScheme, includes R5RS).
> > (require just-the-facts)
> > (fact 5)
> 120
> > (fact 'a)
> 6:3: top-level broke the contract (-> number? number?) on fact;  
> expected <number?>, given: a
>
> Now, a question about the design of modules with contracts. I don't  
> know what kind of overhead contracts place on code: I assume it is  
> either minimal, or noteworthy (meaning "enough that it might  
> matter"). Therefore, it is common or bad practice to write code like:
>
> (module just-fact mzscheme
>   (provide fact)
>   (define (fact n)
>     (if (zero? n)
>         1
>         (* n (fact (sub1 n))))))
>
> (module fact-with-contract mzscheme
>   (require (lib "contract.ss"))
>   (require just-fact)
>   (provide/contract (fact (-> number? number?))))
>
> (module fact-without-contract mzscheme
>   (require just-fact)
>   (provide fact))
>
> Assuming that this code gets used like:
>
> Welcome to DrScheme, version 350.
> Language: Textual (MzScheme, includes R5RS).
> > (require (prefix fwc: fact-with-contract))
> > (fwc:fact 5)
> 120
> > (fwc:fact 'a)
> 6:3: top-level broke the contract (-> number? number?) on fwc:fact;  
> expected <number?>, given: a
> > (require (prefix fw/oc: fact-without-contract))
> > (fw/oc:fact 5)
> 120
> > (fw/oc:fact 'a)
> . zero?: expects argument of type <number>; given a
>
> That is, the module with contracts and the module without contracts  
> provide identical exports, but one attaches contracts to the  
> exports, while the other does not.
>
> I can think of plenty of reasons why this is not a good idea; are  
> there any reasons it is a good idea, and does anyone use the module/ 
> contract system this way in practice?
>
> Cheers,
> M
> _________________________________________________
>  For list-related administrative tasks:
>  http://list.cs.brown.edu/mailman/listinfo/plt-scheme



Posted on the users mailing list.