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

From: Harry Spier (vasishtha.spier at gmail.com)
Date: Fri Dec 14 18:15:37 EST 2012

What Ryan describes is what I was asking for but I  now see what
Matthias's saying, that the contract information belongs in the
interface at the top of the module.

The Racket Guide section on contracts starts out with provide
(contract/out . . .  at the start of the module but from section 7.3.2
onwards a lot of the examples have(provide (contract/out ... after the
function definition.

Thanks,
Harry Spier

On Fri, Dec 14, 2012 at 11:55 AM, Ryan Culpepper <ryan at cs.utah.edu> wrote:
> I understood the feature request differently. I take it as wanting to write
> a module like the following:
>
> #lang racket
> (provide
>   (with-declared-contracts-out
>     f
>     g))
>
> (declare-contract f ....)
> (define f ....)
>
> (declare-contract g ....)
> (define g ....)
>
> That is, the contracts themselves are near the functions, so it's easy to
> keep them in sync. And one can find the names provided by just looking at
> the top of the module---but you only get the names, not the contracts, so
> the interface is incomplete.
>
> This should be easily doable with some compile-time state.
>
> Ryan
>
>
>
>
> On 12/14/2012 11:41 AM, Greg Hendershott wrote:
>>
>> 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
>>
>> _________________________
>>    Racket Developers list:
>>    http://lists.racket-lang.org/dev
>>
>

Posted on the dev mailing list.