[racket-dev] Feature request - contract form that splits provide/contract into two parts
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
>