[racket-dev] Removing Xexpr preference from Web Server

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Mon Dec 6 11:55:23 EST 2010

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.mccarthy at 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 <robby at eecs.northwestern.edu
> > wrote:
>
>> On Mon, Dec 6, 2010 at 9:23 AM, Jay McCarthy <jay.mccarthy at 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 <
>> matthias at 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.mccarthy at 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
>> >> >> <matthias at 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 <jay at 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 <jay at 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 <jay at 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 <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 93
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/dev/archive/attachments/20101206/44719397/attachment.html>

Posted on the dev mailing list.