[racket] style guide, was Re: Contracts and submodules

From: Greg Hendershott (greghendershott at gmail.com)
Date: Tue Mar 5 17:48:51 EST 2013

Oh, wait: module* doesn't have the "combining" behavior of module+. Or
am I misunderstanding?

I've been using the combining behavior of module+ to group tests near
what they test (tests interleaved with definitions).

But it seems like the only choices are:

- Keep using (provide (contract-out)) but switch back to lumping all
the tests together, in one module* (or even back to the old way of a
separate file).

- Keep using module+ but switch back to using define/contract (but
that is much slower as well as being Considered Harmful).

- Keep using both (provide (contract-out)) and module+, but be aware
that the tests won't exercise the module-boundary contracts.

Hmmm.

On Tue, Mar 5, 2013 at 5:00 PM, Greg Hendershott
<greghendershott at gmail.com> wrote:
> That looks great!
>
> On Tue, Mar 5, 2013 at 10:42 AM, Matthias Felleisen
> <matthias at ccs.neu.edu> wrote:
>>
>>
>> P.S. I have re-written chapter 3 of the style guide in particular 3.3 and 3.6 to add your idea:
>>
>>  http://www.ccs.neu.edu/home/matthias/Style/style/Units_of_Code.html
>>
>>
>>
>> On Mar 5, 2013, at 9:59 AM, Matthias Felleisen wrote:
>>
>>>
>>> 1. Clutter removal is built into Racket:
>>>
>>> (define-syntax (interface stx)
>>>  (syntax-case stx (subject-to)
>>>    [(interface name clauses ...)
>>>     ;; ==>
>>>     .. (provide (contract-out ..) ..) ..]))
>>>
>>> The above macro has become a standard in my recent projects where I place it into my ./Lib/contract.rkt library. It is part of an effort to develop a header-file style for Racket. And it is an effort to supply a way to selectively check contracts. [More soon. It is NOT about turning contracts off.]
>>>
>>> 2. Contract test issue acknowledged. I have run into this problem too during my recent construction of a game program. My work-around
>>>
>>> 3. Clutter removal is built into Racket:
>>>
>>> #lang racket
>>>
>>> #lang racket
>>>
>>> (define-syntax-rule
>>>  (tmod def-or-exp ...)
>>>  (module* test racket
>>>    (require rackunit (submod ".."))
>>>    (check-equal? 1 1)
>>>    def-or-exp ...))
>>>
>>> ;; -----------------------------------------
>>>
>>> (provide
>>> (contract-out
>>>  (f (-> integer? integer?))))
>>>
>>> (define (f x) x)
>>>
>>> (tmod (check-equal? (f 2) 2)
>>>      (check-equal? (f 3) 2))
>>>
>>> Consider adding the above module to your ./Lib/contract.rkt library.
>>>
>>>
>>>
>>>
>>>
>>>
>>> On Mar 5, 2013, at 8:39 AM, Greg Hendershott wrote:
>>>
>>>> Not to flog this, but:
>>>>
>>>> Lately I've been trying to be a good little doobie and use `(provide
>>>> (contract-out))` instead of `define/contract`. Although it's more
>>>> typing/clutter, grumble grumble, I've been getting used to it.
>>>>
>>>> Unfortunately I discovered one gotcha: Using (module+ test <rackunit
>>>> tests>) means that the test bypasses the contract -- because it's a
>>>> submodule, and the contract is on the module boundary. So my unit
>>>> tests weren't exercising and validating the contract. I missed a buggy
>>>> contract this way.
>>>>
>>>> In hindsight this is all perfectly obvious. Just not from the guide.
>>>> To be fair using submodules for tests is a relatively recent practice
>>>> in Racket. But I wanted to point out the interaction in case it helps
>>>> anyone else who is trying to use module contracts and do unit tests
>>>> following the curent examples.
>>>>
>>>> One way to avoid this problem is instead of module+ use module*:
>>>>
>>>> (module* test racket ;; To test module-boundary contracts, must use
>>>>                      ;; module* and (require (submod "..")).
>>>>   (require (submod ".."))
>>>>   ... check check check ...
>>>>   )
>>>>
>>>> Of course this adds even more "clutter", but it works.
>>>>
>>>> On Thu, Dec 27, 2012 at 3:31 PM, Matthias Felleisen
>>>> <matthias at ccs.neu.edu> wrote:
>>>>>
>>>>> I have added a note on this issue to the Style issue; see section 3.6. Strictly speaking, this prose probably belongs into the Contract guide. -- Matthias
>>>>>
>>>>>
>>>>>
>>>>> On Nov 30, 2012, at 5:17 PM, Ryan Culpepper wrote:
>>>>>
>>>>>> You can have mutually recursive functions with define/contract, but you can't with submodules.
>>>>>>
>>>>>> Ryan
>>>>>>
>>>>>> On 11/30/2012 05:04 PM, Ray Racine wrote:
>>>>>>> Why not make this explicit by deprecating define/contract and support
>>>>>>> this use case with a submodule.  They lightweight enough and makes
>>>>>>> boundary demarcations consistent, explicit and simple.  Module -> boundary.
>>>>>>>
>>>>>>> On Nov 30, 2012 12:05 PM, "Matthias Felleisen" <matthias at ccs.neu.edu
>>>>>>> <mailto:matthias at ccs.neu.edu>> wrote:
>>>>>>>
>>>>>>>
>>>>>>>  On Nov 30, 2012, at 10:15 AM, Greg Hendershott wrote:
>>>>>>>
>>>>>>>>> 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.
>>>>>>>
>>>>>>>
>>>>>>>  Apologies. My opening wasn't meant to say "I am smarter" but I wanted
>>>>>>>  to send a strong message about define/contract. It really introduces a
>>>>>>>  boundary and in some strange sense your (possibly misleading)
>>>>>>>  microbenchmark
>>>>>>>  exposes this constraint too.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>  ____________________
>>>>>>>     Racket Users list:
>>>>>>>  http://lists.racket-lang.org/users
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> ____________________
>>>>>>> Racket Users list:
>>>>>>> http://lists.racket-lang.org/users
>>>>>>>
>>>>>>
>>>>>> ____________________
>>>>>> Racket Users list:
>>>>>> http://lists.racket-lang.org/users
>>>>>
>>>>>
>>>>> ____________________
>>>>> Racket Users list:
>>>>> http://lists.racket-lang.org/users
>>>
>>>
>>> ____________________
>>>  Racket Users list:
>>>  http://lists.racket-lang.org/users
>>


Posted on the users mailing list.