<div dir="ltr">Good evening Mathias,<div><br></div><div>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.</div><div><br></div><div>Thanks Mathias! Your examples have helped to sharpen my understanding of how contract boundaries work.</div><div><br></div><div>Alex</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 2, 2014 at 2:36 PM, Matthias Felleisen <span dir="ltr"><<a href="mailto:matthias@ccs.neu.edu" target="_blank">matthias@ccs.neu.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
If you use this as the program:<br>
<span class=""><br>
#lang racket<br>
<br>
;; contracts set up boundaries between two regions of a program, say two modules<br>
<br>
;; ---------------------------------------------------------------------------------------------------<br>
;; the library<br>
</span><span class="">(provide (contract-out<br>
           [struct bezier-control-point ((x (and/c number? (between/c 0 1))) (y number?))]<br>
           [cubic-bezier (-> bezier-control-point?<br>
                             bezier-control-point?<br>
                             (->* ((and/c number? (between/c 0 1)))<br>
                                  (#:clamp-range boolean?)<br>
                                  number?))]))<br>
<br>
(struct bezier-control-point (x y) #:transparent)<br>
<br>
(define (cubic-bezier a b)<br>
  ;; now produce a curve via Bezier triangulation<br>
  (lambda (x #:clamp-range [cr #f])<br>
    x))<br>
<br>
</span><span class="">;; ---------------------------------------------------------------------------------------------------<br>
;; the module that uses it<br>
</span>(module+ test<br>
 (require (submod ".."))<br>
<span class=""><br>
 (define a (bezier-control-point 0.1 5.0))<br>
 (define b (bezier-control-point 0.3 9.0))<br>
<br>
 ((cubic-bezier a b)<br>
  ;; a contract violation because i isn't comparable<br>
  (sqrt -1)))<br>
<br>
<br>
</span>drracket or raco test file.rkt will show contract errors.<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
<br>
<br>
On Oct 2, 2014, at 1:50 PM, Alexander McLin <<a href="mailto:alex.mclin@gmail.com">alex.mclin@gmail.com</a>> wrote:<br>
<br>
> 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.<br>
><br>
> Matthias,<br>
><br>
> 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.<br>
><br>
> 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.<br>
><br>
> 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.<br>
><br>
><br>
><br>
> On Thu, Oct 2, 2014 at 9:20 AM, Matthias Felleisen <<a href="mailto:matthias@ccs.neu.edu">matthias@ccs.neu.edu</a>> wrote:<br>
><br>
> Let's make Spencer's question concrete. Say we have this situation:<br>
><br>
> #lang racket<br>
><br>
> ;; contracts set up boundaries between two regions of a program, say two modules<br>
><br>
> ;; ---------------------------------------------------------------------------------------------------<br>
> ;; the library<br>
> (module server racket<br>
>   (provide (contract-out<br>
>             [struct bezier-control-point ((x (and/c number? (between/c 0 1))) (y number?))]<br>
>             [cubic-bezier (-> bezier-control-point?<br>
>                               bezier-control-point?<br>
>                               (->* ((and/c number? (between/c 0 1)))<br>
>                                    (#:clamp-range boolean?)<br>
>                                    number?))]))<br>
><br>
>   (struct bezier-control-point (x y) #:transparent)<br>
><br>
>   (define (cubic-bezier a b)<br>
>     ;; now produce a curve via Bezier triangulation<br>
>     (lambda (x #:clamp-range [cr #f])<br>
>       x)))<br>
><br>
> ;; ---------------------------------------------------------------------------------------------------<br>
> ;; the module that uses it<br>
> (module client racket<br>
>   (require (submod ".." server))<br>
><br>
>   (define a (bezier-control-point 0.1 5.0))<br>
>   (define b (bezier-control-point 0.3 9.0))<br>
><br>
>   ((cubic-bezier a b)<br>
>    ;; a contract violation because i isn't comparable<br>
>    (sqrt -1)))<br>
><br>
> ;; ---------------------------------------------------------------------------------------------------<br>
> ;; run program run<br>
> (require 'client)<br>
><br>
> I assume you want to see other violations. Can you explain with this example w/o going into Bezier?<br>
> (I just know enough about Bezier to draw curves.)<br>
><br>
> -- Matthias<br>
><br>
><br>
><br>
><br>
> On Oct 1, 2014, at 10:46 PM, Alexander McLin <<a href="mailto:alex.mclin@gmail.com">alex.mclin@gmail.com</a>> wrote:<br>
><br>
> > Hello,<br>
> ><br>
> > 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.<br>
> ><br>
> > 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.<br>
> ><br>
> > 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.<br>
> ><br>
> > Here are the contracts I defined provisionally:<br>
> ><br>
> > (provide (contract-out<br>
> >           [struct bezier-control-point ((x (and/c number? (between/c 0 1)))<br>
> >                                                       (y number?))]<br>
> >           [cubic-bezier (-> bezier-control-point?<br>
> >                                      bezier-control-point?<br>
> >                                     (->* ((and/c number? (between/c 0 1)))<br>
> >                                            (#:clamp-range boolean?)<br>
> >                                            number?))]))<br>
> ><br>
> > 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.<br>
> ><br>
> > How can I attach a more complex contract to cubic-bezier's value?<br>
> ><br>
> > Thank you<br>
> > Alexander McLin<br>
> > ____________________<br>
> >  Racket Users list:<br>
> >  <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
><br>
><br>
<br>
</div></div></blockquote></div><br></div>