[racket] Understanding contracts

From: Alexander McLin (alex.mclin at gmail.com)
Date: Thu Oct 2 13:50:42 EDT 2014

Spencer, I'm calling cubic-bezier from within a (module+ test (require
submod "..")...) form that itself is defined in the file where cubic-bezier
is defined. Also I tried from within REPL and requiring the code file.

Matthias,

I ran your example and it works exactly the way I wanted. The lambda
returned from cubic-bezier properly raises contract violations when bad
inputs are given for the required parameter and optional keyword.

Examining the differences between your example and my original
implementation, my functions are directly defined in top level in the file,
after #lang racket, not wrapped within a module. And I'm running my test
cases within a (module+ test (require submod "..")) form.

In my test cases within (module+ test...), violations are correctly
reported when I give bad inputs to cubic-bezier and bezier-control-point
structs. Except the lambda, no violations are reported with bad inputs. Is
it because I'm incorrectly using modules? I had thought that module+ and
(require submod "..") would allow the contract system to come into full
force.



On Thu, Oct 2, 2014 at 9:20 AM, Matthias Felleisen <matthias at ccs.neu.edu>
wrote:

>
> Let's make Spencer's question concrete. Say we have this situation:
>
> #lang racket
>
> ;; contracts set up boundaries between two regions of a program, say two
> modules
>
> ;;
> ---------------------------------------------------------------------------------------------------
> ;; the library
> (module server racket
>   (provide (contract-out
>             [struct bezier-control-point ((x (and/c number? (between/c 0
> 1))) (y number?))]
>             [cubic-bezier (-> bezier-control-point?
>                               bezier-control-point?
>                               (->* ((and/c number? (between/c 0 1)))
>                                    (#:clamp-range boolean?)
>                                    number?))]))
>
>   (struct bezier-control-point (x y) #:transparent)
>
>   (define (cubic-bezier a b)
>     ;; now produce a curve via Bezier triangulation
>     (lambda (x #:clamp-range [cr #f])
>       x)))
>
> ;;
> ---------------------------------------------------------------------------------------------------
> ;; the module that uses it
> (module client racket
>   (require (submod ".." server))
>
>   (define a (bezier-control-point 0.1 5.0))
>   (define b (bezier-control-point 0.3 9.0))
>
>   ((cubic-bezier a b)
>    ;; a contract violation because i isn't comparable
>    (sqrt -1)))
>
> ;;
> ---------------------------------------------------------------------------------------------------
> ;; run program run
> (require 'client)
>
> I assume you want to see other violations. Can you explain with this
> example w/o going into Bezier?
> (I just know enough about Bezier to draw curves.)
>
> -- Matthias
>
>
>
>
> On Oct 1, 2014, at 10:46 PM, Alexander McLin <alex.mclin at gmail.com> wrote:
>
> > Hello,
> >
> > I've been working on a sample project to better understand how to use
> the contract system. I created a simple Bezier curve implementation and am
> using (provide (contract-out...) to attach contracts to the provided
> bindings.
> >
> > Basically I have a procedure called cubic-bezier that accepts two
> control point structs used to define the curve. It returns another
> procedure that actually generates the curve, it accepts an integer
> parameter that lies on [0, 1] and an optional keyword #:clamp-range. The
> generator procedure returns a number.
> >
> > The control point structure is a simple posn type that accepts X and Y
> fields where X must be between 0 and 1, and Y is allowed to be any number.
> >
> > Here are the contracts I defined provisionally:
> >
> > (provide (contract-out
> >           [struct bezier-control-point ((x (and/c number? (between/c 0
> 1)))
> >                                                       (y number?))]
> >           [cubic-bezier (-> bezier-control-point?
> >                                      bezier-control-point?
> >                                     (->* ((and/c number? (between/c 0
> 1)))
> >                                            (#:clamp-range boolean?)
> >                                            number?))]))
> >
> > For the contract attached to cubic-bezier using ->, my thinking was to
> use ->* to generate the contract for the procedure returned by cubic-bezier
> but it's not working, meaning I'm not getting the any contract violations
> I'm expecting when giving bad inputs to cubic-bezier's value.
> >
> > How can I attach a more complex contract to cubic-bezier's value?
> >
> > Thank you
> > Alexander McLin
> > ____________________
> >  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/20141002/73c5b8bd/attachment.html>

Posted on the users mailing list.