Compiler CPS Transformations

It looks like people are now writing compilers to deal with node js spaghetti callback code. These are available for C#, Javascript (useable with nodejs) and Scala.

C# 5.0

C# 5.0 will have await/async keywords

http://msmvps.com/blogs/jon_skeet/archive/2011/05/08/eduasync-part-1-introduction.aspx

you can write non-blocking http handler like:

public async void get(Request request, Response response) {
  var json = await Redis.get(request.getParam("id"));
  await response.write(json);
}

Redis#get and Reponse#write are both async methods

if you need to do parallel handling:

public async void get(Request request, Response response) {
  var json1Task = Redis.get(request.getParam("id"));
  var json2Task = Redis.get(request.getParam("id"));

  await response.write(await json1Task + await json2Task);
}

Scala

Scala has continuations using the shift/reset keywords which seems to be much harder to grock than await/async.

http://www.scala-lang.org/node/2096

However, if you wrote a proper non-blocking library you would probably never use shift/reset in client code. it would all be in the library. if you have a shift which is not nested in a reset then the method becomes CPS and if you have a method that calls a CPS method it becomes CPS as well. it spreads a bit like a virus infecting everything it touches. so it is mostly transparent.

you can write non-blocking http handler like:

def get (request: Request, response: Response) = {
  val json = Redis.get(request.getParam("id"))
  response.write(json)
}

#get, Redis#get and Reponse#write are all CPS.

if you need to do parallel handling then:

def get (request: Request, response: Response) = {
  val json1Future = Redis.getAsync(request.getParam("id1"))
  val json2Future = Redis.getAsync(request.getParam("id2"))

  response.write(json1Future.await, json2Future.await)
}

here Future#await, #get and Response#write are CPS. Redis#getAsync is a normal method that returns a Future that has a CPS await method.

the main difference between c# and scala is in c# the caller is able to choose whether they want to (appear to) block on an async method while in scala the callee has to expose a blocking and a non-blocking version of the method. It appears to be possible to create a function that convert a CPS blocking method to a method that returns a Future. I have some code that does it for 1/arity methods. https://gist.github.com/1191571 I suspect that there is a much simpler way of doing it but I don’t understand scala continuations enough to work it out :)

Javascript

For javascript there are many options

Streamline JS (https://github.com/Sage/streamlinejs) has been written specifically for nodejs.

You can write a non-blocking http handler like so:

function get(request, response, _) {
  var json = Redis.get(request.getParam("id"), _);
  response.write(json, _);
}

which compiles to:

function get(request, response, _) {
  var json;
  var __frame = {
    name: "get",
    line: 1
  };
  return __func(_, this, arguments, get, 2, __frame, function __$get() {
    return Redis.get(request.getParam("id"), __cb(_, __frame, 1, 13, function ___(__0, __1) {
      json = __1;
      return response.write(json, __cb(_, __frame, 2, 2, _));
    }));
  });
};

There is also TameJS which doesn’t have magical error handling:

https://github.com/maxtaco/tamejs

You can write a non-blocking http handler like so:

function get(request, response) {
  await {Redis.get(request.getParam("id"), defer(var err, var json))};
  // error handling cut out
  await {response.write(json, defer(var err))};
  // error handling cut out
}

There is also:
Narrative JS (http://www.neilmix.com/narrativejs/doc/example.html)
Stratify JS (http://onilabs.com/stratifiedjs)

and there was an attempt to get a defer keyword added to coffee script

https://github.com/jashkenas/coffee-script/issues/350

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.