[racket-dev] Feature request - contract form that splits provide/contract into two parts

From: Greg Hendershott (greghendershott at gmail.com)
Date: Fri Dec 14 11:41:36 EST 2012

Matthias has vastly more experience and perspective in matters like
this; you would be wise to prefer his advice.

But if I understand correctly what you want, I think you could do this
yourself with a simple macro:

(define-syntax define/contract/provide
  (syntax-rules ()
    [(_ (id . args) contract body ...)
     (begin
       (define/contract (id . args) contract body ...)
       (provide id))]
    [(_ id contract expr)
     (begin
       (define/contract id contract expr)
       (provide id))]))

That's the version I've used in some past projects. However: It uses
define/contract promiscuously, which is (a) not universally beloved
and (b) much slower than provide/contract in the current version of
Racket.

Instead I think you could flip it around to use provide/contract, instead:

(define-syntax define/provide/contract
  (syntax-rules ()
    [(_ (id . args) contract body ...)
     (begin
       (provide/contract (id . args) contract body ...)
       (define id))]
    [(_ id contract expr)
     (begin
       (provide/contract id contract expr)
       (define id))]))

I _think_ that's essentially what you're asking for?

(Of course this means the function won't be protected by a contract
when called from inside the module, which could be considered bad,
good, or N/A. Just be aware.)

Any approach not using a single provide/contract list has the
disadvantage that Matthias explained: The module no longer has a
contiguous description of its interface in the source.

That's a serious disadvantage. Some might consider it mitigated if the
module has Scribble documentation. Also someone reading the source
might "collapse" in Emacs (or whatever) to quickly see all the
top-level definitions (although that would include any non-provided
items, so it's not perfect (unless the stock collapse is customized)).

You could also put a list in comments, I suppose.

On Fri, Dec 14, 2012 at 10:44 AM, Matthias Felleisen
<matthias at ccs.neu.edu> wrote:
>
> It is critical to inform clients of the services that a module
> provides. In the absence of types, contracts are the closest
> information we have. Reading the implementation is against
> all good SE ideas.
>
> IF we could assume that people always programmed in DrRacket,
> we could compromise and add a tool that synthesizes the interface
> of a module in some way. Since some contributors break this guideline
> all the time anyway, we should have such a tool available anyway.
>
> BUT there are also people who use Emacs and the other editor.
>
> So, if you want to be good, put provide contract-out at the top
> of your module.
>
>
>
>
>
> On Dec 14, 2012, at 1:02 AM, Harry Spier wrote:
>
>> If you place provide/contract at the beginning of a module it makes
>> the interface clear but it is separated from its function.  If you
>> place it right before its function and not at the top of the module,
>> it makes the function clearer but the module interface is not so
>> clear.
>>
>> Is it possible (would it be a good idea?) to provide a new form that
>> splits the provide/contract form into two parts.  One part the
>> contract definition which you could place immediately before the
>> function definition and the second part a provide spec for inclusion
>> in a provide statement that included the function name but not the
>> contract spec.) .  That way the contract definition can be by the
>> function definition and the function name can be in a provide
>> statement at the beginning of the module.
>>
>> Harry Spier
>> _________________________
>>  Racket Developers list:
>>  http://lists.racket-lang.org/dev
>
> _________________________
>   Racket Developers list:
>   http://lists.racket-lang.org/dev

Posted on the dev mailing list.