[racket] rudimentary Q. about lambda + contracts

From: Alexander D. Knauth (alexander at knauth.org)
Date: Mon Nov 18 17:59:58 EST 2013

If I were making something like case-lambda/contract, which would be  
better/make more sense?

#lang racket

(require test-engine/racket-tests)

;; this one takes a contract within each case, and puts in in a case->  
for you:
(define-syntax-rule (case-lambda/contract-1 [args c e0 e ...] ...)
   (let ()
     (define/contract f
       (case-> c ...)
       (case-lambda
         [args e0 e ...]
         ...))
     f))

;; example for case-lambda/contract-1:
(define report-cost-1
   (case-lambda/contract-1
     [(lo hi) (integer? integer? . -> . string?)
      (format "between $~a and $~a" lo hi)]
     [(desc) (string? . -> . string?)
      (format "~a of dollars" desc)]))

(check-expect (report-cost-1 5 8)
               "between $5 and $8")
(check-expect (report-cost-1 "millions")
               "millions of dollars")
(check-error (report-cost-1 "thousands" "millions"))
(check-error (report-cost-1 5))


;; this one takes a contract for the whole thing, and lets you do the  
case-> yourself:
(define-syntax-rule (case-lambda/contract-2 contract-expr [args e0  
e ...] ...)
   (let ()
     (define/contract f
       contract-expr
       (case-lambda
         [args e0 e ...]
         ...))
     f))

;; example for case-lambda/contract-2:
(define report-cost-2
   (case-lambda/contract-2
     (case->
       (integer? integer? . -> . string?)
       (string? . -> . string?))
     [(lo hi) (format "between $~a and $~a" lo hi)]
     [(desc) (format "~a of dollars" desc)]))

(check-expect (report-cost-2 5 8)
               "between $5 and $8")
(check-expect (report-cost-2 "millions")
               "millions of dollars")
(check-error (report-cost-2 "thousands" "millions"))
(check-error (report-cost-2 5))


(test)


Which one is better/makes more sense?

(define report-cost-1
   (case-lambda/contract-1
     [(lo hi) (integer? integer? . -> . string?)
      (format "between $~a and $~a" lo hi)]
     [(desc) (string? . -> . string?)
      (format "~a of dollars" desc)]))

(define report-cost-2
   (case-lambda/contract-2
     (case->
       (integer? integer? . -> . string?)
       (string? . -> . string?))
     [(lo hi) (format "between $~a and $~a" lo hi)]
     [(desc) (format "~a of dollars" desc)]))


On Nov 17, 2013, at 12:43 PM, Matthias Felleisen wrote:

>
> I would choose option 2, because I have a strong preference for  
> seeing specs first and ignoring implementations if I can. You may  
> wish to ask on the list; others may have other ideas. -- Matthias
>
>
>
>
>
> On Nov 16, 2013, at 11:05 AM, Alexander D. Knauth wrote:
>
>> If I were making something like this for case-lambda, which would  
>> be better/make more sense?
>>
>> #lang racket
>>
>> (require test-engine/racket-tests)
>>
>> ;; this one takes a contract within each case, and puts in in a  
>> case-> for you:
>> (define-syntax-rule (case-lambda/contract-1 [args c e0 e ...] ...)
>>   (let ()
>>     (define/contract f
>>       (case-> c ...)
>>       (case-lambda
>>         [args e0 e ...]
>>         ...))
>>     f))
>>
>> ;; example for case-lambda/contract-1:
>> (define report-cost-1
>>   (case-lambda/contract-1
>>     [(lo hi) (integer? integer? . -> . string?)
>>      (format "between $~a and $~a" lo hi)]
>>     [(desc) (string? . -> . string?)
>>      (format "~a of dollars" desc)]))
>>
>> (check-expect (report-cost-1 5 8)
>>               "between $5 and $8")
>> (check-expect (report-cost-1 "millions")
>>               "millions of dollars")
>> (check-error (report-cost-1 "thousands" "millions"))
>> (check-error (report-cost-1 5))
>>
>>
>> ;; this one takes a contract for the whole thing, and lets you do  
>> the case-> yourself:
>> (define-syntax-rule (case-lambda/contract-2 contract-expr [args  
>> body ...] ...)
>>   (let ()
>>     (define/contract f
>>       contract-expr
>>       (case-lambda
>>         [args body ...]
>>         ...))
>>     f))
>>
>> ;; example for case-lambda/contract-2:
>> (define report-cost-2
>>   (case-lambda/contract-2
>>     (case->
>>       (integer? integer? . -> . string?)
>>       (string? . -> . string?))
>>     [(lo hi) (format "between $~a and $~a" lo hi)]
>>     [(desc) (format "~a of dollars" desc)]))
>>
>> (check-expect (report-cost-2 5 8)
>>               "between $5 and $8")
>> (check-expect (report-cost-2 "millions")
>>               "millions of dollars")
>> (check-error (report-cost-2 "thousands" "millions"))
>> (check-error (report-cost-2 5))
>>
>>
>> (test)
>>
>>
>> Which one is better/makes more sense?
>>
>> (define report-cost-1
>>   (case-lambda/contract-1
>>     [(lo hi) (integer? integer? . -> . string?)
>>      (format "between $~a and $~a" lo hi)]
>>     [(desc) (string? . -> . string?)
>>      (format "~a of dollars" desc)]))
>>
>> (define report-cost-2
>>   (case-lambda/contract-2
>>     (case->
>>       (integer? integer? . -> . string?)
>>       (string? . -> . string?))
>>     [(lo hi) (format "between $~a and $~a" lo hi)]
>>     [(desc) (format "~a of dollars" desc)]))
>>
>>
>> On Nov 13, 2013, at 2:45 PM, Matthias Felleisen wrote:
>>
>>>
>>> Do you want something like this :
>>>
>>> #lang racket
>>>
>>> (define-syntax-rule
>>>  (lambda/contract (x ...) c e0 e ...)
>>>  ;; ==>
>>>  (let ()
>>>    (define/contract (f x ...) c e0 e ...)
>>>    f))
>>>
>>> ;;  
>>> -----------------------------------------------------------------------------
>>>
>>> (define g (lambda/contract (x) (integer? . -> . integer?) (* pi x)))
>>>
>>> (void (= (g 0) 0))
>>> (with-handlers ([exn:fail:contract? void])
>>>  (g 1))
>>>
>>>
>>>
>>>
>>>
>>> On Nov 13, 2013, at 1:12 PM, Matthew Butterick <mb at mbtype.com>  
>>> wrote:
>>>
>>>> Having gotten in the habit of writing function contracts, I  
>>>> prefer define/contract to (provide (contract-out ...)) because it  
>>>> keeps the contract near the function.
>>>>
>>>> Is there an analogous idiom for lambda? I see there is no lambda/ 
>>>> contract, and the docs on contracts for case-lambda [1] uses the  
>>>> (provide (contract-out ...)) style.
>>>>
>>>> [1] http://docs.racket-lang.org/guide/contracts-general-functions.html#(part._contracts-case-lambda)
>>>> ____________________
>>>> Racket Users list:
>>>> http://lists.racket-lang.org/users
>>>
>>>
>>> ____________________
>>>  Racket Users list:
>>>  http://lists.racket-lang.org/users
>>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20131118/85430aa2/attachment-0001.html>

Posted on the users mailing list.