[racket] Understanding contracts

From: Alexander McLin (alex.mclin at gmail.com)
Date: Fri Oct 3 21:59:47 EDT 2014

Good evening Mathias,

After studying your program and mine, and running various permutations, I
understand where I was going wrong. It appears that while doing manual
experimentation I had gotten confused to which module I was actually in the
REPL when calling various functions by hand. Also my test cases weren't
fine grained enough to detect each unique contract violation generated by
suitable bad inputs.

Thanks Mathias! Your examples have helped to sharpen my understanding of
how contract boundaries work.

Alex

On Thu, Oct 2, 2014 at 2:36 PM, Matthias Felleisen <matthias at ccs.neu.edu>
wrote:

>
> If you use this as the program:
>
> #lang racket
>
> ;; contracts set up boundaries between two regions of a program, say two
> modules
>
> ;;
> ---------------------------------------------------------------------------------------------------
> ;; the library
> (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+ test
>  (require (submod ".."))
>
>  (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)))
>
>
> drracket or raco test file.rkt will show contract errors.
>
>
>
>
> On Oct 2, 2014, at 1:50 PM, Alexander McLin <alex.mclin at gmail.com> wrote:
>
> > 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/20141003/06727941/attachment-0001.html>

Posted on the users mailing list.