[racket] Making a contract between a function and "the world in general"
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.
Ryan