On Mon, Dec 6, 2010 at 10:23 AM, Robby Findler <ro...@eecs.northwestern.edu>wrote:
> On Mon, Dec 6, 2010 at 11:19 AM, Jay McCarthy <jay.mccar...@gmail.com> > wrote: > > > > > > On Mon, Dec 6, 2010 at 10:16 AM, Robby Findler < > ro...@eecs.northwestern.edu> > > wrote: > >> > >> Who should be blamed if the coercion does not return a response? > > > > The provider of the coercion should be blamed, but that is not possible > [I > > think] so the positive party of the whole dynamic/c is blamed. > > Can you show us an example use of this contract from the web server? > The HEAD Web Server has this definition of response/c: (define response/c (or/c response/basic? (cons/c bytes? (listof (or/c string? bytes?))) pretty-xexpr/c)) My local changes have: (define current-response/c (make-parameter any/c)) (define response/c (dynamic/c any/c current-response/c response?)) My compatibility library is just a module with this body: (current-response/c (coerce/c normalize-response)) where normalize-response is the function (basically) that the old Web Server always used before relying on anything in particular about a response and coerce/c is a trivial thing that turns a coercion into a contract: (define (coerce/c i->o) (make-contract #:name (build-compound-type-name 'coerce i->o) #:projection (λ (b) (λ (x) (or (i->o x) (raise-blame-error b x "Coercion failed")))))) My local copy will also provide xexpr-response/c: (define xexpr-response/c (coerce/c (λ (x) (cond [(response? x) x] [(xexpr? x) (response/xexpr x)] [else #f])))) which many users will want to use as a current-response/c, although I will not ship any code that uses it exist for test cases. Jay > > >> Is there a contract on current-response/c? (I assume that the "/c" > >> there is a misnomer and it really is a parameter that holds a > >> contact/coercion, not a contract.) > > > > current-response/c is contracted with (parameter/c contract?) > > The /c is not a misnomer, you are just parsing it wrong. Read it as > > (parameter (contract response)) not (contract (parameter response)), > where > > /c is the post-fix syntax for (contract x) and current- is the pre-fix > > syntax for (parameter x) > > Ah. I see. > > Robby > > > > >> > >> Robby > >> > >> On Mon, Dec 6, 2010 at 10:55 AM, Jay McCarthy <jay.mccar...@gmail.com> > >> wrote: > >> > Maybe dynamic/c isn't clear enough... its definition is pretty short: > >> > (define (dynamic/c pre parameter post) > >> > (define pre-ctc (coerce-contract 'pre pre)) > >> > (define post-ctc (coerce-contract 'post post)) > >> > (make-contract > >> > #:name (build-compound-type-name 'dynamic pre-ctc parameter > post-ctc) > >> > #:projection > >> > (λ (b) > >> > (define pre-proj ((contract-projection pre-ctc) b)) > >> > (define post-proj ((contract-projection post-ctc) b)) > >> > (λ (x) > >> > (define dyn-proj > >> > ((contract-projection (coerce-contract 'dynamic (parameter))) > >> > b)) > >> > (post-proj > >> > (dyn-proj > >> > (pre-proj > >> > x))))))) > >> > The system provides pre and post, so it can offer protection to the > >> > coercion > >> > as well as receive protection FROM the coercion. But the coercion > comes > >> > from > >> > a parameter which is exposed to the user. > >> > The one I use in the web-server is: > >> > (dynamic/c any/c current-response/c response?) > >> > where response? is the data structure predicate that the internal > >> > plumbing > >> > uses. > >> > Jay > >> > On Mon, Dec 6, 2010 at 9:51 AM, Jay McCarthy <jay.mccar...@gmail.com> > >> > wrote: > >> >> > >> >> That's why dynamic/c has a pre/c and post/c. Before it uses the > user's > >> >> contract, it applies pre/c. After it applies post/c. This ensures > that > >> >> the > >> >> user's contract actually coerces to a response? > >> >> Jay > >> >> > >> >> On Mon, Dec 6, 2010 at 9:25 AM, Robby Findler > >> >> <ro...@eecs.northwestern.edu> wrote: > >> >>> > >> >>> On Mon, Dec 6, 2010 at 9:23 AM, Jay McCarthy < > jay.mccar...@gmail.com> > >> >>> wrote: > >> >>> > Yes, since I am allowing users to customize the coercion behavior, > I > >> >>> > could > >> >>> > either have them provide two functions: a coercion-applies? > function > >> >>> > and a > >> >>> > coercion function; OR I could have them just provide the coercion > >> >>> > function > >> >>> > and I will check the answer and re-run it inside of the function > >> >>> > body. > >> >>> > > >> >>> > The other issue is that finding all the places where I should > apply > >> >>> > the > >> >>> > coercion inside the body of the function is difficult, because I > >> >>> > need > >> >>> > to do > >> >>> > it at every place where a response/c could flow in (relatively > easy) > >> >>> > and > >> >>> > every place where a response/c could flow out (much hard, esp. > with > >> >>> > continuations). Contracts on functions are very nice in their > >> >>> > ability > >> >>> > to do > >> >>> > stuff to inputs and outputs. > >> >>> > >> >>> > >> >>> I think I need more help to understand the programming problem > better. > >> >>> Why are your users supplying you a contract that you are using to > >> >>> protect your functions? That is how can you use anything about that > >> >>> contract to avoid errors in your programs? > >> >>> > >> >>> Robby > >> >>> > >> >>> > Jay > >> >>> > > >> >>> > On Mon, Dec 6, 2010 at 8:19 AM, Matthias Felleisen > >> >>> > <matth...@ccs.neu.edu> > >> >>> > wrote: > >> >>> >> > >> >>> >> The string->number primitive is probably closer to what Jay wants > >> >>> >> to > >> >>> >> do. > >> >>> >> > >> >>> >> The only contract I can think of for string->number is > >> >>> >> > >> >>> >> ;; Number -> Boolean > >> >>> >> (define (string->number-able? x) > >> >>> >> (number? (string->number x))) > >> >>> >> > >> >>> >> So the real problem is a performance problem, which a lazy > >> >>> >> interpretation > >> >>> >> of contracts by the compiler might be able to eliminate. > >> >>> >> > >> >>> >> Is this the true problem Jay -- Matthias > >> >>> >> > >> >>> >> > >> >>> >> > >> >>> >> > >> >>> >> > >> >>> >> > >> >>> >> > >> >>> >> > >> >>> >> On Dec 6, 2010, at 9:45 AM, Robby Findler wrote: > >> >>> >> > >> >>> >> > Let's be clear here: our inability to enforce projectionness is > >> >>> >> > in > >> >>> >> > no > >> >>> >> > way condoning the two coercianlike contracts that you have now > >> >>> >> > written. > >> >>> >> > > >> >>> >> > That said, the only value I see to contracts that only signal > >> >>> >> > errors > >> >>> >> > (or do nothing) is that programmers know what to expect from > >> >>> >> > them. > >> >>> >> > The > >> >>> >> > downsides you mention are well taken, of course. > >> >>> >> > > >> >>> >> > In this specific case, your message seems slightly confused: > >> >>> >> > certainly > >> >>> >> > you should be able to use a contract to ensure that the > coercion > >> >>> >> > will > >> >>> >> > always succeed. Let's assume you have done that and now discuss > >> >>> >> > only > >> >>> >> > where the coercing bit of the "contract" goes. Is it in a > higher > >> >>> >> > order > >> >>> >> > position? Is it something that describes an interface to your > >> >>> >> > module > >> >>> >> > or can it be considered an internal detail? > >> >>> >> > > >> >>> >> > As a possible guide by analogy, consider the path-string? > >> >>> >> > Predicate. > >> >>> >> > It is the contract on many functions the ultimately is > connected > >> >>> >> > to > >> >>> >> > some kind of a coercion somehwere buried inside the racket > >> >>> >> > primitives > >> >>> >> > for dealing with the filesystem. Is that like what you want to > >> >>> >> > do? > >> >>> >> > If > >> >>> >> > so, how would your arguments hold up for that part of our > system? > >> >>> >> > > >> >>> >> > Robby > >> >>> >> > > >> >>> >> > On Monday, December 6, 2010, Jay McCarthy > >> >>> >> > <jay.mccar...@gmail.com> > >> >>> >> > wrote: > >> >>> >> >> These contracts are not thrown "at dynamic places". The > contract > >> >>> >> >> is > >> >>> >> >> always at the module boundary/etc, but its meaning if affected > >> >>> >> >> by > >> >>> >> >> the > >> >>> >> >> dynamic context of the particular boundary crossing. [1] > >> >>> >> >> > >> >>> >> >> I'm been thinking about why I want to use contracts for this > >> >>> >> >> purpose. > >> >>> >> >> The alternative is to put an any/c contract in all the places > I > >> >>> >> >> currently have response/c and as the first thing in all those > >> >>> >> >> functions call > >> >>> >> >> current-any->response [or as the last thing on returns] on the > >> >>> >> >> input > >> >>> >> >> argument. I would then have to put a note in all the > >> >>> >> >> documentation > >> >>> >> >> of those > >> >>> >> >> any/c that it doesn't REALLY accept anything, instead in other > >> >>> >> >> accepts > >> >>> >> >> things that the dynamic current-any->response will turn into a > >> >>> >> >> response. If > >> >>> >> >> the coercion failed, then I would have to throw an error, > which > >> >>> >> >> be > >> >>> >> >> purely > >> >>> >> >> dynamic with no blame information because it would not be > >> >>> >> >> associated with a > >> >>> >> >> contract boundary. > >> >>> >> >> > >> >>> >> >> In contrast, using a contract for this purpose allows me to > >> >>> >> >> centralize > >> >>> >> >> the documentation and behavior of these arguments, get correct > >> >>> >> >> blame on > >> >>> >> >> places where the coercion fails, and abstract the coercion out > >> >>> >> >> of > >> >>> >> >> the code > >> >>> >> >> that is using it into its interface. These are all great wins. > >> >>> >> >> > >> >>> >> >> In my opinion, if I did not use contracts, the only elegant > >> >>> >> >> thing > >> >>> >> >> to do > >> >>> >> >> would be to recreate something almost exactly like the > contract > >> >>> >> >> system but > >> >>> >> >> called the coercion system. That is absurd to me when > contracts > >> >>> >> >> already do > >> >>> >> >> exactly this. > >> >>> >> >> > >> >>> >> >> Am I just not clever enough to think of another elegant way? > >> >>> >> >> Why is there so much resistance to using the contract system > in > >> >>> >> >> a > >> >>> >> >> perfectly legal way according to its own definition & > contracts? > >> >>> >> >> [2] [i.e. > >> >>> >> >> "projection" functions are not forced to be projections by any > >> >>> >> >> means. / > >> >>> >> >> contracts already break eq?/equal?-ness / etc] > >> >>> >> >> > >> >>> >> >> Jay > >> >>> >> >> 1. We already have such context-sensitive contracts: > >> >>> >> >> > >> >>> >> >> > >> >>> >> >> > >> >>> >> >> > http://docs.racket-lang.org/xml/index.html#(def._((lib._xml/main..rkt)._permissive/c)) > >> >>> >> >> > >> >>> >> >> permissive/c exists to allow DrRacket to embed more snips > inside > >> >>> >> >> the > >> >>> >> >> XML boxes, which are otherwise not XML elements. > >> >>> >> >> 2. make-contract's projection keyword has the contract (-> > any/c > >> >>> >> >> any/c) > >> >>> >> >> > >> >>> >> >> The example of make-contract coerces the procedure by > >> >>> >> >> restricting > >> >>> >> >> how > >> >>> >> >> many arguments rather than checking that when it is given that > >> >>> >> >> number of > >> >>> >> >> arguments it is used properly, etc. > >> >>> >> >> > >> >>> >> >> Only flat and chaperone contracts attempt to enforce > >> >>> >> >> projection-ness. > >> >>> >> >> On Sun, Dec 5, 2010 at 9:31 AM, Matthias Felleisen > >> >>> >> >> <matth...@ccs.neu.edu> wrote: > >> >>> >> >> > >> >>> >> >> Jay, coercions aka casts in our world are compound words with > -> > >> >>> >> >> in > >> >>> >> >> between them. Why do you need a new name? > >> >>> >> >> > >> >>> >> >> (There is an inconsistency in their behavior. To wit > >> >>> >> >> > >> >>> >> >> Welcome to Racket v5.0.99.4. > >> >>> >> >>> (integer->char 1000000000000000) > >> >>> >> >> integer->char: expects argument of type <exact integer in > >> >>> >> >> [0,#x10FFFF], > >> >>> >> >> not in [#xD800,#xDFFF]>; given 1000000000000000 > >> >>> >> >> > >> >>> >> >> === context === > >> >>> >> >> /Users/matthias/plt/collects/racket/private/misc.rkt:78:7 > >> >>> >> >>> (string->number "a10") > >> >>> >> >> #f > >> >>> >> >> > >> >>> >> >> But that is a historical problem.) > >> >>> >> >> > >> >>> >> >> ;; --- > >> >>> >> >> > >> >>> >> >> I am also reluctant to throw contracts at dynamic places. > >> >>> >> >> Contract > >> >>> >> >> boundaries should be syntactically distinct, e.g., module > >> >>> >> >> boundaries or > >> >>> >> >> define/contract. > >> >>> >> >> > >> >>> >> >> ;; --- > >> >>> >> >> > >> >>> >> >> I think you're really just checking an assertion. So perhaps > you > >> >>> >> >> want > >> >>> >> >> to go with /a as a suffix. > >> >>> >> >> > >> >>> >> >> > >> >>> >> >> -- Matthias > >> >>> >> >> > >> >>> >> >> > >> >>> >> >> > >> >>> >> >> > >> >>> >> >> -- > >> >>> >> >> Jay McCarthy <j...@cs.byu.edu> > >> >>> >> >> Assistant Professor / Brigham Young University > >> >>> >> >> http://faculty.cs.byu.edu/~jay > >> >>> >> >> > >> >>> >> >> "The glory of God is Intelligence" - D&C 93 > >> >>> >> >> > >> >>> >> >> > >> >>> >> > >> >>> > > >> >>> > > >> >>> > > >> >>> > -- > >> >>> > Jay McCarthy <j...@cs.byu.edu> > >> >>> > Assistant Professor / Brigham Young University > >> >>> > http://faculty.cs.byu.edu/~jay > >> >>> > > >> >>> > "The glory of God is Intelligence" - D&C 93 > >> >>> > > >> >> > >> >> > >> >> > >> >> -- > >> >> Jay McCarthy <j...@cs.byu.edu> > >> >> Assistant Professor / Brigham Young University > >> >> http://faculty.cs.byu.edu/~jay > >> >> > >> >> "The glory of God is Intelligence" - D&C 93 > >> > > >> > > >> > > >> > -- > >> > Jay McCarthy <j...@cs.byu.edu> > >> > Assistant Professor / Brigham Young University > >> > http://faculty.cs.byu.edu/~jay > >> > > >> > "The glory of God is Intelligence" - D&C 93 > >> > > > > > > > > > -- > > Jay McCarthy <j...@cs.byu.edu> > > Assistant Professor / Brigham Young University > > http://faculty.cs.byu.edu/~jay > > > > "The glory of God is Intelligence" - D&C 93 > > > -- Jay McCarthy <j...@cs.byu.edu> Assistant Professor / Brigham Young University http://faculty.cs.byu.edu/~jay "The glory of God is Intelligence" - D&C 93
_________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev