<div dir="ltr"><div><div><div>In my poorly-informed point of view, I use contracts only to make checks, so that they can be deactivated to run the code in faster/less-error-friendly mode if needed and when I'm sufficiently confident the program is good enough, and if the program crashes anyway, restart it in slower/safe mode with contracts, get into exactly the same situation and have better debug info.<br>
</div></div>(Although I have planned to do that for a long time, I've never actually completely done it yet. Contracts could also be checked at different boundaries just by switching a value.)<br></div>I wonder if people would consider that bad practice too btw, since it does not seem to exist already in Racket, AFAICT.<br>
<div><div><div><div><br></div><div>Laurent<br></div><div><br></div></div></div></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sun, Feb 16, 2014 at 1:09 AM, Matthew Butterick <span dir="ltr"><<a href="mailto:mb@mbtype.com" target="_blank">mb@mbtype.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
Of course, these are not really contracts as we understand them. The docs for 'make-contract' say not to do this, if you read them carefully. So beware. I'm kind of curious what other people think of this application of the contract system, actually.</blockquote>
<div><br></div></div><div>Why is it an abuse of the contract system to define a contract that uses a projection to change the value? </div><div><br></div><div>The docs for make-contract say "The projection must either produce the value, <b>suitably wrapped to enforce any higher-order aspects of the contract</b>, or signal a contract violation." Is it never true that changing a value can be the "suitable wrapping"? (Or m I overlooking some other relevant part of the docs?)</div>
<div><br></div><div>Consider this contract. It checks whether a value can be converted to a path. If so, it returns the converted value. If not, it fails. (This one's in quasicode, but I wrote a real one and it works as expected.) If this is abuse, it's very useful abuse.</div>
<div><br></div><div><div>(define coerce/path?</div><div> (make-contract</div><div> #:name 'coerce/path?</div><div> #:projection (ë (b)</div><div> (ë (x)</div><div> (if (can-be-path? x)</div>
<div> (convert-to-path x)</div><div> (raise-blame-error</div><div class=""><div> b x</div><div> '(expected: "~a" given: "~e")</div>
</div><div> 'can-be-path? x))))))</div></div><div><div class="h5"><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><br><div class="gmail_extra"><br><br><div class="gmail_quote">
On Mon, Nov 18, 2013 at 10:25 AM, Ryan Culpepper <span dir="ltr"><<a href="mailto:ryanc@ccs.neu.edu" target="_blank">ryanc@ccs.neu.edu</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><div>On 11/18/2013 12:03 PM, Matthew Butterick wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
In a function that permits liberal inputs, I often find that the input processing I do in a contract is duplicated at the beginning of the body of the function. Is this avoidable?<br>
<br>
Certain functions want to be liberal with input because there are multiple common ways to represent the data. For instance, I have a function that operates on CSS RGB colors. This function should be prepared to accept these forms of input & understand that they're all the same:<br>
<br>
"#c00"<br>
"#cc0000"<br>
'("204" "0" "0")<br>
#xcc0000<br>
'(0.8 0 0)<br>
<br>
Let's say that my internal representation of an RGB color is described by the contract rgb-color/c:<br>
<br>
(define rgb-color/c (list/c (real-in 0 1) (real-in 0 1) (real-in 0 1)))<br>
<br>
But I can't use rgb-color/c as the input contract for the function because it's too narrow. So I make a second contract that tests for things that can be converted to an rgb-color:<br>
<br>
(define (rgb-colorish? x) (or/c rgb-color/c [tests for the other input formats ...] )<br>
<br>
To determine if the input is rgb-colorish?, this contract usually just ends up trying to convert the input to rgb-color. If it works, then the contract returns true.<br>
<br>
But after the contract returns, I have to convert the input to an rgb-color anyhow. So I'm doing exactly the same work that the contract just finished. If the conversion is expensive, I'm doing it twice.<br>
</blockquote>
<br></div></div>
We usually just don't worry about the conversion happening twice. Or we do what Matthias said. Or we apply a fast approximate contract (or none at all) and then do the conversion and error checking together inside the function.<br>
<br>
But... by abusing the contract system a little bit, though, we can get it to do the conversion for you.<br>
<br>
Here's a "contract" combinator that takes a conversion function that returns #f to indicate failure/rejection and any other value to represent the converted result.<br>
<br>
> (define (make-named-conversion-<u></u>contract name convert)<br>
(define ((proj blame) v)<br>
(cond [(convert v )<br>
=> values]<br>
[else<br>
(raise-blame-error blame v<br>
'(expected: "~a" given: "~e")<br>
name v)]))<br>
(make-contract #:name name #:projection proj))<br>
<br>
Here's a "contract" that checks that a value is real, and if so produces its absolute value.<br>
<br>
> (define abs/c<br>
(make-named-conversion-<u></u>contract<br>
'abs/c<br>
(lambda (v) (and (real? v) (abs v)))))<br>
<br>
And here's a function using the converting "contract":<br>
<br>
> (define/contract f (-> abs/c real?)<br>
(lambda (x) x))<br>
> (f 10)<br>
10<br>
> (f -12) ;; <-- !!!<br>
12<br>
> (f 'hello)<br>
f: contract violation<br>
expected: abs/c<br>
given: 'hello<br>
....<br>
<br>
Of course, these are not really contracts as we understand them. The docs for 'make-contract' say not to do this, if you read them carefully. So beware. I'm kind of curious what other people think of this application of the contract system, actually.<span><font color="#888888"><br>
<br>
Ryan</font></span><div><div><br>
<br>
____________________<br>
Racket Users list:<br>
<a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/<u></u>users</a><br>
</div></div></blockquote></div><br></div></div></div></div>
<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></blockquote></div><br></div>