Monday, May 18, 2009

The Two State Solution: Native and Serializable Continuations in the PLT Web Server

One of the annoyance of the stateless Web application language that comes with the PLT Web Server is that you can't call third-party higher-order library procedures with arguments that try to capture serializable continuations. (I know, you try to do that all the time.) For example:

(build-list
 3
 (lambda (i)
   (call-with-serializable-current-continuation
    (lambda (k) (serialize k)))))

The problem is that the stateless language performs a transformation on your program to extract the continuations into a serializable representation. If you really need to do this, we've developed a compromise called "The Two State Solution": one state on the client and the other on the server. Only the third-party parts of the continuation (in this case, the code inside build-list) are stored on the server; everything else is shipped to the client. You just need to annotate your code slightly to indicate where the transition is:

(serial->native
 (build-list
  3
  (lambda (i)
    (native->serial
     (call-with-serializable-current-continuation
      (lambda (k) (serialize k)))))))

serial->native signals the transition to the third-party and native->serial signals the transition back.

It is still a little annoying to find when you've called these third-party higher-order library procedures with arguments that try to capture serializable continuations, so there's a simple macro that provides a transitioning wrapper for you:

(define-native (build-list/native _ ho) build-list)

expands to:

(define (build-list/native fst snd)
  (serial->native
   (build-list
    fst
    (lambda args
      (native->serial
       (apply snd args))))))

This new feature is documented in the online manual, of course.

Soft State in the PLT Web Server

Many Web applications and network protocols have values in the continuation that are necessary to complete the computation, but that may be recomputed if they are not available. This is "soft state".

For example, a Web application may cache a user's preferences from a database and deliver it to a Web browser as a hidden value; when the value is returned to the application in subsequent steps, it is used to customize the display. However, if the preferences were not available (or were corrupted in some way), the application could retrieve them from the database.

When using the PLT Web Server's native continuations, this roughly corresponds to the use of a weak box: a box that the GC is allowed to erase the contents of. When using the PLT Web Server's serializable continuations it roughly corresponds to a weak box and a weak hash table (that holds its keys weakly) to give the box a serializable value as an identifier.

This programming pattern is a bit difficult to get right. So, a library that implements it is now provided with PLT Scheme: web-server/lang/soft.

Here's a trivial example:

#lang web-server

(provide interface-version start)
(define interface-version 'stateless)

(define softie
  (soft-state
   (printf "Doing a long computation...~n")
   (sleep 1)))

(define (start req)
  (soft-state-ref softie)
  (printf "Done~n")
  (start
   (send/suspend
    (lambda (k-url)
      `(html (body (a ([href ,k-url]) "Done")))))))

Wednesday, May 13, 2009

Jesus and the Eyewitnesses, by Richard Bauckham

Jesus and the Eyewitnesses, by Richard Bauckham

This book defends the thesis that the Gospels (Matthew, Mark, Luke, and John) are collection of eyewitness testimonies. Bauckham discusses ancient and modern historiography to show how such gathering of testimony was (and is) common when writing this sort of history. He places much emphasis on the inclusion of specific names as a key to the origin of the particular testimony. His main narrative is derived from Papias who writes that he is recording stories that have been circulating and given by eyewitnesses, because the original testators are slowly dying and the stories must be maintained.

I'm not really qualified to judge much of the book, so I skimmed some of the more esoteric segments. The closing essay, "The Jesus of Testimony" was particularly interesting. He starts with Kevin Vanhoozer's technical definition of testimony: "Testimony is a speech act in which the witness's very act of stating p is offered as evidence 'that p,' it being assumed that the witness has the relevant competence or credentials to state truly 'that p.'" [pg 473] Bauckham argues that we rely on testimony "hundreds, probably thousands, of times a day in trivial ways and in crucially important ways" [pg 474], so why should be particular skeptical of testimony in historical contexts?

After a long discussion of the reasonableness of trusting testimony, Bauckham makes a long analogy between testimonies of the Holocaust and the testimonies of Jesus:

Holocaust testimonies are not easily appropriated by the historian, since they are prima facie scarcely credible and since they defy the usual categories of historical explanation. (Charlotte Delbo said of new arrivals in Auschwitz what is also true of any who read Holocaust testimonies: "They expect the worst --- they do not expect the unthinkable.") This is why the testimonies of survivors of the Holocaust are in the highest degree necessary to any attempt to understand what happened. The Holocaust is an event whose reality we could scarcely begin to imagine if we had not the testimonies of survivors.

In the Gospels, if we believe them, we also have to do with an event "at the limits." The comparison is hazardous. In almost everything except the sheer historical exceptionality of the event, the Holocaust and the history of Jesus have nothing in common. Our argument is in no way intended to detract from the particular uniqueness of the Holocaust. On the contrary, we have to appreciate this uniqueness if the case of the Holocaust is to teach us anything about the role of testimony in other cases of exceptionality in history. [pg 493]

Overall, this is a very interesting book that is a bit of antidote to the general skepticism about the New Testament Gospels.

Tuesday, May 5, 2009

What is send/suspend?

I often ponder what send/suspend really is. It is a lot like call/cc, but has the curious property that the continuation escapes in a single way and is only called in a particular context. I often wonder if there is something weaker than call/cc that implements send/suspend.

Today I wrote a little dispatcher that uses threads to implement send/suspend. In this implementation, sending truly suspends the computation.

Here's the code: http://www.copypastecode.com/codes/view/5003

The trick is to have channels for communicating responses and requests. When you run this example, you should be able to add two numbers. But, in contrast to the normal send/suspend, all the URLs are one-shots, because once the computation is resumed, it moves forward... it is never saved.

This implementation technique also precludes clever implementations of send/suspend/dispatch, like:

(define (send/suspend/dispatch mk-page)
  (let/cc k0
    (send/back
     (mk-page
      (lambda (handler)
        (let/ec k1 
          (k0 (handler (send/suspend k1)))))))))

Saturday, May 2, 2009

New Moon, by Stephenie Meyer

New Moon (The Twilight Saga, Book 2), by Stephenie Meyer

I was very impressed how different this was from Twilight, both in style and plot. There was definitely no surprise for the "big reveal", because I knew it was going to happen before opening the book (based on my intuition, not any spoiler.) BUT, all the details and everything that happened after that was very interesting and surprising. The one problem with this book, IMHO, is that it doesn't stand alone as well as Twilight, so I really feel like I must read the rest of the books, whereas after Twilight I could have gone either way.