[racket] Making a contract between a function and "the world in general"

From: Ryan Culpepper (ryan at cs.utah.edu)
Date: Sat Oct 8 21:49:34 EDT 2011

On 10/08/2011 10:12 AM, Matthias Felleisen wrote:
> (2) I object to
>   provide-with-whatever-contract-you-already-have
> because I think programmers should explicitly state what
> they want (if they want something logical).
> We can already do this
>   (define primes-to-primes (->  (listof prime?) (listof prime?)))
>   (provide/contract
>     [f primes-to-primes]
>     [primes-to-primes contract?])
> So in some client module we can write
>   (provide/contract
>     [f primes-to-primes])
> again.

I don't understand the benefit to your approach. I'd like to write 
something like the following this:

   (provide (re-contract-out f))

I believe your objection is that the contract for f is not manifest in 
this module: we have to chase down the source of f to find its contract. 
Perhaps you would say that re-contract-out is bad the way type inference 
for top-level functions is bad, and explicit contracts are better the 
way that explicit type declarations are better.

But in your alternative,

   (provide (contract-out [f contract-of-f]))

the contract of f is *still* not manifest in the module. Instead of 
chasing down f, we have to chase down contract-of-f. We've also 
duplicated code/knowledge (the association between f and contract-of-f) 
with all the problems that entails. Also, we've cluttered up the 
namespace with these contract-of-* bindings.

Of course, duplicating the contract expression would make it manifest, 
but it would aggravate the ill effects from code duplication. My 
experience: partly because of its lazy-require tricks, the db library 
has some duplication of contracts, and I hate it. I've also eliminated 
internal contracts to avoid having to repeat them in the 
externally-visible modules.


Posted on the users mailing list.