[racket-dev] Removing Xexpr preference from Web Server
On Mon, Dec 6, 2010 at 10:23 AM, Robby Findler
<robby at eecs.northwestern.edu>wrote:
> On Mon, Dec 6, 2010 at 11:19 AM, Jay McCarthy <jay.mccarthy at gmail.com>
> wrote:
> >
> >
> > On Mon, Dec 6, 2010 at 10:16 AM, Robby Findler <
> robby at 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.mccarthy at 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.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
> >> >
> >
> >
> >
> > --
> > 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/cba981b4/attachment.html>