[racket-dev] Removing Xexpr preference from Web Server

From: YC (yinso.chen at gmail.com)
Date: Mon Dec 6 14:53:41 EST 2010

Wow - the thread doubled in size overnight ;)

On Mon, Dec 6, 2010 at 9:39 AM, Robby Findler
<robby at eecs.northwestern.edu>wrote:

> In other words, this seems like a step backwards from a "do I, as a
> client of the webserver, understand the API of the webserver and can I
> program to it?" perspective.

This is why I said that having a default is good for users - and xexpr is a
good default.  The refactoring will obviously improve architecture of
web-server and increase its utility, but many users will not likely tap into
those utilities, and hence backward compatibility needs is high.  Hence my
original proposal of web-server2, but in lieu of the desire to keep
web-server name and involve, the following signature will probably be what
most users are willing to do to upgrade:

Change from

(require web-server)


(require web-server/<compat-layer-here)

So if users can just do the above and keep every other code exactly the
same, then the compatibility goal has been achieved, and the rest is to
figure out how to get there.  I think Jay's approach is quite close to what
will work for everyone.  Below are my 2 cents to help with the issues being
raised, instead of raising more issues, hopefully.

1 - having implemented extension hooks in many of my packages, I've learned
that extensions are hard to implement as a parameter in the presence of
threads, especially if the extensions are done during module requirement
time.  Since each new thread will not do the module require process again,
and they will end up with the values prior to the extension modules.  So
unless Jay takes care of the parameterizations somehow implicitly, the users
will need to write their own parameterization code, which will be as much
work as just calling make-xexpr-response if not more.

I would suggest making the extension mechanism global.  As I mentioned
earlier - all hooks should be registered during the module require time, and
hence the side effect do not exist during the runtime.  This is basically
equivalent to define a new function, which is a side effect against the
namespace table.

2 - extension/coercion can work within the confines of contract, via the
following approach:

Provide two hooks - one for response-coercible?, and the other for

The response-coercible? hooks has the following definitions:

;; response-coercible?-hook (-> any/c any)
(define (response-coercible? v)
  (or (response? v) (response-coercible?-hook v)))

Also provide a way to set the response-coercible? hook, something like
(define-reponse-coercible-hook ...)

The any->response hook is what has been discussed thus far:

;; any->response-hook: (-> any/c response?)
(define (any->response v)
  (if (response? v)
      (any->response-hook v)) )

Then the web-server's response output mechanism can simply have the
following contract:

(-> response-coercible? any)

3 - there are two ways to do the hooks here - one is to provide a dispatch
table for multiple types, so the users do not have to handle their own
dispatching based on the types, and the other is to delegate the
responsibility of dispatching to people who need to customize these hooks.

The dispatching code will likely to impose a particular order of evaluation,
and that can make some types difficult to discern apart (for example - xexpr
vs string vs sxml), so this, and the fact that it is simpler (for now),
might favor to delegate the dispatching to the users who customize.

Delegating away the dispatching table, the hooks are simply a field.

(define response-coercible?-hook default-response-coercible?-hook)

(define (define-response-coercible-hook?! hook)
  (set! response-coercible?-hook hook))

  (define-response-coercible?-hook! (-> (-> any/c any) any)))

And the same with the any->response-hook.

4 - It's okay to push multiple hooks and the dispatching to users who wish
to customize, since these users are likely wanting to control the
dispatching to ensure a precise evaluation order - I know I will want to
control that process myself.

For users who want custom behavior without the work - well, they can always
wait for lib writers to come up with the hooks for them.

Hope the above sketch makes sense, the actual implementation to make it work
will obviously differ from the above depending on other requirements Jay
needs to satisfy.

My 2 cents.  Cheers,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/dev/archive/attachments/20101206/d9cf3c6a/attachment.html>

Posted on the dev mailing list.