[racket] Contracts and submodules

From: Greg Hendershott (greghendershott at gmail.com)
Date: Fri Nov 30 10:15:38 EST 2012

> This is a complete misunderstanding.

Sometimes I feel like a kid in the room while the adults are talking.
When it comes to contracts, I have to stipulate that most of you are
smarter than me and have thought about this longer than me.

Having stipulated that, it seems unfortunate and surprising that

(define/contract (f x)
  (integer? . -> . any)

is ~200 times slower than

(define (f x)
  (unless (integer? x) (raise-argument-error ....))

It seems like "pro" Racket code avoids the former and does the latter.
One reason may be that such code predates contracts, and/or old habits
die hard. But another reason seems to be that the former would be
unacceptably slow. I wish it weren't.

Are you saying that "contract" is a fundamentally different concept
than "argument checking" -- it's not a superset but some whole
different beast?  If so, then I guess I'm saying I want something with
the declarative convenience of define/contract (or syntax-parse), but
fast enough to be practical. I could refer to this other concept as
"term sheets" (i.e. a light 2-page memo rather than a 100-page
agreement) to avoid confusion. I've sketched that out and could just
use that myself instead of disturbing you all with this feedback.

On Fri, Nov 30, 2012 at 9:33 AM, Matthias Felleisen
<matthias at ccs.neu.edu> wrote:
> On Nov 29, 2012, at 10:29 PM, Greg Hendershott wrote:
>> AFIK these subtleties of contracts and modules arise with
>> `provide/contract' -- by saying that the function should only use a
>> contract outside the module (or submodule).
>> But I prefer to use `define/contract'. For one thing, I think it's
>> easier and more-maintainable to group the contract near/with its
>> function in the source. But I also prefer it on the starting
>> assumption that if a procedure is worth contracting at all, it's worth
>> contracting all the time -- inside the module as well as outside.
> This is a complete misunderstanding. Contracts are specifications
> that govern the flow of values across boundaries. We call this boundary
> a 'module' but for several years now, module and #lang have been two
> distinct terms. In this spirit,
>  -- #lang with provide contract-out is a module
>  -- define/contract is a module
>  -- internal modules are modules but watch out for module+
> In contrast,
>  -- units and classes are values and we have contracts for them
>         but they do NOT establish contract boundaries, they are
>         NOT modules.
> In your specific case, define/contract splits an existing 'module'
> into two pieces.
> ;; ---
> As I have said many times, your use of contract is likely to be
> much better satisfied with the use of Typed Racket. I doubt that
> many of your contracts are checking more than constructors, which
> roughly corresponds to type checking. For the remaining ones, Sam
> will provide
>   provide/typed with contract-out
>   require/typed with contract-in
>         ANY TIME SOON NOW.
> ;; ---
> As for performance of contracts:
> On Nov 29, 2012, at 11:47 PM, Harry Spier wrote:
>> And then to enable/disable contracts you can use the method Mathias
>> pointed out here.
>> http://www.mail-archive.com/users@racket-lang.org/msg12281.html
> Thanks for reminding the list of this post. I should write this
> out as a blog post or an entry into our Contract Guide.

Posted on the users mailing list.