[racket] contracts on functions that take arbitrary keyword arguments

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Sat Dec 28 09:59:08 EST 2013

1. I am stumped. I don't know how to write a contract for my-send. 

2. I see what you want to do and I think you should seriously consider a different protocol: 

(define (get-vector this)
  (vector (send this get-x) (send this get-y))) 

For something like get-vector, I'd create a contract constructor that ensures its argument is an object with a get-x and a get-y method. I'd use a contract constructor because I suspect you want contracts for more than get-vector. This could also be lifted into syntax so that you can generate the contract constructor for classes like this. And you might equip the contract constructor with more specific constraints for its arguments and return values. 

-- Matthias






On Dec 28, 2013, at 2:43 AM, Alexander D. Knauth <alexander at knauth.org> wrote:

> The problem isn't with defining the function, the problem is with making a contract for it.  
> 
> I can define the function fine, I just don't know how to write a contract for it.  I used make-keyword-procedure to define the function, but is there something like make-keyword-procedure-contract?  I could write my own error code, but it would be better if I could express it as a contract.  
> 
> The actual concrete example is that I'm making my own version of send that works with method-like procedures.  
> 
> #lang racket
> 
> (define/contract current-send-object (parameter/c (or/c object? #f))
>   (make-parameter #f))
> 
> (define my-send
>   (make-keyword-procedure
>    (lambda (kws kw-args object proc . rest-args)
>      (parameterize ([current-send-object object])
>        (keyword-apply proc kws kw-args rest-args)))))
> 
> (define point%
>   (class object%
>     (super-new)
>     (init-field [x 0] [y 0])
>     (define/public (get-x) x)
>     (define/public (get-y) y)))
> 
> (define (get-vector)
>   (let* ([object (current-send-object)]
>          [x (send object get-x)]
>          [y (send object get-y)])
>     (vector x y)))
> 
> (define p (new point% [x 3] [y 5]))
> 
> (require rackunit)
> 
> (check-equal? (my-send p get-vector)
>               (vector 3 5))
> 
> (check-equal? (my-send p (compose vector->list get-vector))
>               (list 3 5))
> 
> that way you can define new "methods" without them being specified by the class, and they're first class functions.  I wanted to be able to make a contract for my-send (and my-send/apply etc.) that would check that object is an object and that proc is a procedure, but still take arbitrary keyword arguments and just pass them on to proc.  
> 
> On Dec 27, 2013, at 1:03 PM, Matthias Felleisen wrote:
> 
>> 
>> This is a bit vague. Can you clarify the question with a concrete example? 
>> 
>> 
>> On Dec 26, 2013, at 7:45 PM, "Alexander D. Knauth" <alexander at knauth.org> wrote:
>> 
>>> I want to make contracts on some apply-like functions that check some arguments but just passes all the others (including keyword arguments) on to a function (provided as an argument).  If there weren't any keyword arguments, I could use a rest argument to do this, but that wouldn't work with keyword arguments.  Is there a way to do something like a rest argument for keyword-arguments in a contract?____________________
>>> Racket Users list:
>>> http://lists.racket-lang.org/users
>> 
> 



Posted on the users mailing list.