7 Dec 2007

by Noel

Announcing: Delirium

Delirium is a web-browser automation toolkit, which means it’s a Scheme library that provides a bunch of functions that you can use to control a web browser. We expect the primary use will be for web testing, and Delirium can be used inside SchemeUnit like any other Scheme library.

For the Schemers Delirium isn’t anything special, but we believe the use of continuations make Delirium a major advance over similar web testing tools like Selenium. If you write your server code in Scheme you can directly test how your server side responds to web tests with tests running on the same server. That is to say a test can interleave calls to the web browser and to the server side code, which is impractical without continuations. This features makes it much easier to write reliable and comprehensive tests.

Delirium is on PLaneT. Note the documentation was translated by hand from Scribble source. Some errors may have been introduced during the translation.

Posted in Web development | Comments Off on Announcing: Delirium

7 Dec 2007

by Noel

ICFP 2007 In Review

At last — the long awaited ICFP post! In summary: ICFP was awesome. Freiburg is lovely, the German beer is fantastic, and everyone at the conference was very friendly. It was great to put faces to people we’ve conversed with for years, to meet old friends, and to make new ones.

We gave two talks, one at ICFP on our work building web sites in Scheme (paper here), and one at CUFP (PLT Slideshow slides PDF slides). Both were, I think, well received: a few people expressed some interest in having us come and talk to their groups, and the CUFP organisers invited us to join them at dinner.

There was a definite buzz about ICFP. It seems functional languages are beginning to take off — CUFP doubled its attendence over last year, and ICFP strained the capacity of the hotel. There was something of a reality distortion field in place though. After a few days at the conference you could begin to believe the entire software market consisted of either program verification tools in Haskell or telephony apps in Erlang. There was little representation from web developers, who I think must make up the largest group of commercial developers. I believe this is because Haskell users really dominate ICFP, and Haskell doesn’t have a particularly good web development story as far as I know.

It was interesting to see how the other communities are developing. The Haskell guys had a 3-day Hackathon right after ICFP, which is pretty impressive, and there is a practical Haskell book in development, something which is needed for Scheme. Erlang seemed to have slightly better industry representation and also has several recent practically-oriented publications. I heard that many people had arrived just for the Erlang workshop, which was held the day after CUFP.

Of course the conference revolved around the paper presentations. There were too many to review them all, so I’ll just note the ones that were particularly relevant to our work at Untyped.

Matthew Flatt’s talk on Adding Delimited and Composable Control to a Production Programming Environment was a great presentation on a new feature in PLT Scheme, delimited continuations, that will be very useful in the web server. Matthew hacked Slideshow (something you can do when you’re the core developer) to support animations by quickly fading between slides. His 1028 slides made for some slick animations that quickly and clearly got across the concept of delimited continuations. This was perhaps the best presentation I saw at the conference and it was on something we’ll definitely be using.

The iData toolkit is a Clean library that uses meta-programming to generate code for viewing and editing arbitrary data online (like Ruby on Rail’s scaffolding, but better). At ICFP this year the followup,iTasks: Executable Specifications of Interactive Work Flow Systems for the Web, was presented. Essentially it is a combinator library for specifying workflows, including higher-order workflows. At is happens we may soon be involved in a project that deals with workflows, in which case we’ll review this work.

I really liked Advanced Macrology and the Implementation of Typed Scheme by Ryan Culpepper, Sam Tobin-Hochstadt, and Matthew Flatt. Typed Scheme is pretty cool, and we’ll probably use it when it has matured a bit more, but my favourite bit of this paper is the first half which is essentially a tutorial on intermediate to advanced macrology. There is precious little material available on this corner of Scheme, so it is very welcome addition.

Also of particular interest to us were Applications of Fold to XML Transformation, and Software Transactions Meet First-Class Continuations. We’ve already had occasion to use ideas from the former, while the later gave us some food for thought with regards toSnooze We had an interesting conversation with Adam Wingo, author of the paper on folds, about the advantages of distributed version control. Something we need to look into. Adam also has a great job that allows him to spend two days a week hanging out in Barcelona’s cafes. Some people get all the luck.

One point from ICFP that is particularly relevant for this blog: Dave Herman told me he’d like to see more technical posts. I’ve tried to make the content a bit more technical of late, but if there is anything in particular you’d like me to write about drop me a line.

Posted in Code | Comments Off on ICFP 2007 In Review

7 Dec 2007

by Noel

ICFP 2007 In Fashion

Naturally no meeting of computer scientists would be complete without some mention of fashion. The satorial pinnacle of ICFP was easily claimed by Adrien Pierard who was rocking a bowler hat and pipe combo. I was pleased to find his hat was indeed sourced fromJames Lock & Co. I saw several Threadless t-shirts: The Communist Party, Dark Side of the Garden, and Well This Just Really Sucks. (Follow the first link to Threadless, buy a T-Shirt, and I get $3.00 towards a tee. Follow the other links and I get nadda. Threadless is a great example of a business model that is only possible over the Internet. If you’re not familiar with them, check ‘em out.)

Computer scientists pay almost as much attention to their computers as they do to their clothing. From an informal survey of the conference Apple is continuing its rise in popularity amongst the geek crowd — the ratio of Mac to PCs was about 1:1. Of course a Mac is about as close to a fashion statement as a computer can come, so it isn’t surprising to see this adoption.

Posted in Fun | Comments Off on ICFP 2007 In Fashion

23 Nov 2007

by Noel

Custom Dispatchers in the PLT Scheme Web Server

We’ve just released <a
href=”http://planet.plt-scheme.org/display.ss?package=instaweb.plt&owner=schematics”>Instaweb
2.0. Instaweb is our utility that takes care of setting
up the PLT web-server and running servlets. If you have a
servlet in a file called servlet.ss with
Instaweb you just need to write the following lines to get
it running:

(require (planet "instaweb.ss" ("schematics" "instaweb.plt" 2)))
(instaweb)

The new version of Instaweb includes many new options and
works in a slightly different way to the 1.0 branch. To my
mind the best new feature is that Instaweb now configures
the web-server to pass to the servlet all requests
that don’t match a file in the htdocs
directory. This means your servlet no longer has to live
under a URL starting with /servlets. You can
<a
href=”http://planet.plt-scheme.org/package-source/schematics/instaweb.plt/2/1/doc.txt”>read
the documentation to get the full details of what’s new.
What I want to talk about here is how we implelemented this,
as it illustrates some very nice features of the web-server
that aren’t well known.

In the web-server’s terminology a dispatcher is a
function that may generate a response given a request.
Examples includes the filesystem dispatcher, which responds
to requests with the contents of a file, and the servlet
dispatcher, which invokes a servlet. Dispatchers are
arranged in a list. The first dispatcher in the list
inspects the request and, if it decides the request is
relevant, generates a response. Otherwise control is passed
to the next dispatcher in the list. For some time now the
web-server has had a configurable dispatcher pipeline, which
can be set by simply passing a value with the
#:dispatch keyword to the serve
function.

The web-server provides a number of dispatchers, all in
the <a
href="http://svn.plt-scheme.org/plt/trunk/collects/web-server/dispatchers/">dispatchers

subdirectory of the web-server collection.
They all provide a make function that does most
of the work. Here’s how to use the file, servlet, and
sequence dispatchers, the most generally useful ones:

  1. The file dispatcher, in
    dispatch-files.ss, takes a single parameter, a
    function that converts a URL to a path (and another value
    that the dispatcher ignores). The path can name a file,
    which the dispatcher will serve if such a file actually
    exists, or it can name a directory, in which case the
    dispatcher will look for a file within that directory called
    index.html or index.htm.

    To use the file dispatcher you will probably want the
    handy make-url->path function in
    filesystem-map.ss. Pass this function a base
    path (the directory where your files live), and it will
    return a function suitable to pass to the file
    dispatcher.

    Here’s an example of use:

    (require
    (prefix file: (lib "dispatch-files.ss" "web-server" "dispatchers"))
    (lib "filesystem-map.ss" "web-server" "dispatchers"))
    
    (define base-path (string->path "/my/directory/of/files"))
    
    ;; htdocs-url->path : path -> (url -> path (list-of path-element))
    (define (htdocs-url->path path)
    (make-url->path (path->complete-path path)))
    
    ;; dispatch-htdocs : (connection request -> response)
    (define dispatch-htdocs
    (file:make #:url->path (htdocs-url->path base-path)))
  2. The servlet dispatcher, in dispatch-servlets.ss is a bit more difficult to use as you need a function from the privatesubcollection of the web-server, suggesting the code reorganisation isn’t quite finished. The make function takes two arguments, the first being a cache-table, and the second being a function that, like for the file dispatcher, maps URLs to paths. To construct a cache-table use the following lines of code:
    (require
    (lib "cache-table.ss" "web-server" "private"))
    
    (define cache-table (box (make-cache-table)))

    If you want all URLs to go a particular servlet, as in Instaweb, the URL to path function just needs to return the path of the servlet. The function used in Instaweb is this:

    ;; serlvet-url->path : url -> path (list-of path-element)
    (define (servlet-url->path url)
    (let ([complete-servlet-path (path->complete-path servlet-path)])
    (values complete-servlet-path (explode-path* complete-servlet-path))))

    Now we can create a dispatcher as follows:

    ;; clear-servlet-cache! : -> void
    ;; dispatch-servlets:    connection request -> response
    (define-values (clear-servlet-cache! dispatch-servlets)
    (servlet:make (box (make-cache-table))
    #:url->path servlet-url->path))
  3. The sequencer dispatcher couldn’t be easier to use. It just takes any numbe of dispatchers and creates new dispatcher that tries them in sequence. For example:
    ;; dispatch-all : connection request -> response
    (define dispatch-all
    (sequencer:make dispatch-htdocs
    dispatch-servlets))

With the above you should be able to create your own custom dispatchers. If you have problems just read the (very short) Instaweb code!

Posted in Web development | Comments Off on Custom Dispatchers in the PLT Scheme Web Server

19 Oct 2007

by Noel

Attack of the Spam Bots

Over the last weekend, and sporadically this week, the computer that hosts untyped.com and Untyped’s email server has been under attack from a network of spam bots. It doesn’t appear that we’ve been targeted specifically. Rather, it seems that the bots are scanning for email addresses to spam, presumably to propagate the bots. It took down our email server over the weekend, but we’ve since taken steps to combat the flood of traffic. However, if you sent us an email and are waiting for a response, you might want to send it again.

We’d don’t know what bot is attacking us, but there is a good chance it is the “Storm Worm”. I didn’t know of the Storm Worm before we were attacked; my reading since then indicates it is a truly massive network, with the potential to cause a lot of trouble. This Wired piecediscusses how Estonia was taken off the Internet by a massive bot net attack.

Posted in General | Comments Off on Attack of the Spam Bots

8 Oct 2007

by Noel

Of Interest 08/10/2007

Back from ICFP, but a full review will have to wait. Meanwhile here’s some stuff I saw today that interested me:

  • Y-Combinator tattoo. Ouch! Comments on plt-scheme revolved around the choice of font.
  • From the same discussion came a link to Gentium, which is a very nice font and is also free.

Posted in General | Comments Off on Of Interest 08/10/2007

28 Sep 2007

by Noel

Untyped at ICFP 2007

Dave and I, representing Untyped, will be at the Scheme Workshop,ICFP, and CUFP in Freiburg. If you’re there, do say Hi!

Posted in Fun, Functional Programming, Racket | Comments Off on Untyped at ICFP 2007

23 Aug 2007

by Noel

As recently seen on the Untyped Subversion commit list…

I personally watch commits go by for several projects, and it is instructive in many ways to read the commit messages and code. It is a way to learn new things about the software process as well as the implementation of solutions in code. That said, very occasionally, you actually get a giggle from the process…

Today was one of those times.

Date: 2007-08-22 12:22:06 +0100 (Wed, 22 Aug 2007)
New Revision: 1398
Log:
[DJG] IDCheck trunk:

Tests tests tests.
Date: 2007-08-22 12:41:46 +0100 (Wed, 22 Aug 2007)
New Revision: 1399
Log:
[DJG+NHW] IDCheck trunk:

Testing all the way.
Date: 2007-08-22 12:49:21 +0100 (Wed, 22 Aug 2007)
New Revision: 1400
Log:
[NHW+DJG] IDCheck trunk:

Oh what fun it is to ride on a one horse testing sleigh.

The song ends there, I’m afraid… but it does seem like Dave and Noel are a bit cracked out today. Perhaps they should be out playing frisbee instead of coding this fine Thursday. As I’m not in the same timezone, it’s difficult to say what’s going on over there…

Posted in Code, Fun | Comments Off on As recently seen on the Untyped Subversion commit list…

21 Aug 2007

by Noel

S3 Doesn’t Count the Pennies (Yet)

I use Amazon S3 as an off-site backup for data on my desktop
computer. S3 has two principle advantages: there’s no upper limit on
the amount of data you can transmit or store, and it’s very cheap…
sometimes a little too cheap.

Two days ago I received an auto-generated warning from S3 about my
account status:

Greetings from Amazon Web Services,

AWS was unable to charge your account based on the payment
information you provided. Please update your payment method
information using the Your Web Services Account section of the AWS web
site.

Sincerely,

Amazon Web Services

There were a few extra details in there that convinced me that this
wasn’t spam, but that was the gist of it. I logged on to my account to
find that my balance was a whopping $0.01. A single cent!

I checked my credit card details and they seemed to be okay. I
re-entered them to be on the safe side, and then emailed AWS asking
them to re-try the payment and let me know if it failed again. I
received this response:

Thank you for contacting AWS regarding the payment issue related to
your August 1st bill. We have found that some credit card issuers
decline charges of $0.01 (USD), especially when the amount is
converted to another currency. AWS is working on a solution for this
issue. In the meantime, please contact AWS
directly at webservices@amazon.com if this issue should occur again.

The $0.01 (USD) charge on your August 1st bill has been forgiven,
and your account is in good standing.

A month’s backups, totally free of charge – that’s value
for money. I shall be recommending S3 to all my friends.

Posted in General | Comments Off on S3 Doesn’t Count the Pennies (Yet)

6 Aug 2007

by Noel

Refactoring Functional Programs

A little while ago we<a
href=”http://www.untyped.com/untyping/archives/2007/06/selenium_code_r.html”>released
an interface to Selenium, a web testing framework.
Since then we’ve learned that Selenium is simply too slow to
use in our work-flow. Hence we started on a faster
reimplementation of the Selenium Remote Control.

A key part of this system is a proxy server, which is necessary to get around the same origin security restriction in Javascript. I’ve just finished a large refactoring of the proxy code, and I think the experience is interesting enough to warrant a blog post. While there is a large literature on refactoring object-oriented programs, there is rather less on refactoring functional programs, and what there is tends to concentrate on program transformation tools (long a FP strength) at the expense of collecting useful FP refactorings. This post is a small contribution to redressing the balance.

The code I spent most time on was the HTTP parser. It is structured as a state machine, so the initial version used the classic FP pattern ofmutually tail recursive functions. The code for parsing an HTTP request looked something like this:

(define (parse-request)
(define request-line #f)
(define headers #f)

(define (parse-request-line)
(set! request-line (read-request-line))
(parse-headers))

(define (parse-headers)
(let ([line (read-line)])
(if (end-of-input line)
(begin (set! headers (reverse headers))
(do-something))
(begin (set! headers (cons line headers))
(parse-headers)))))

(parse-request-line))

The code for parsing an HTTP response was very similar:

(define (parse-response)
(define response-line #f)
(define headers #f)

(define (parse-response-line)
(set! response-line (read-response-line))
(parse-headers))

(define (parse-headers)
(let ([line (read-line)])
(if (end-of-input line)
(begin (set! headers (reverse headers))
(do-something-different))
(begin (set! headers (cons line headers))
(parse-headers)))))

(parse-response-line))

The real code was several screens long. I wanted to make it
simpler by changing to a functional style, and reusing
common code between the request and response parsing
functions. Converting to functional style is simple:

(define (parse-request)
(define (parse-request-line)
(define request-line (read-request-line))
(parse-headers request-line))

(define (parse-headers request-line)
(define headers
(let loop ([line (read-line)])
(if (end-of-input line)
null
(cons line (loop (read-line))))))
(do-something request-line headers))

(parse-request-line))

Reusing common code is not simple. The finite state machine
pattern doesn’t abstract the next state. For example
parse-headers in parse-request
always calls do-something whereas the otherwise
identical version in parse-response calls
do-something-different.

I solved this by refactoring the code into<a
href=”http://library.readscheme.org/page6.html”>continuation-passing
style, leading to code that looks like the following:

;; shared between parse-request and parse-response
(define (parse-headers request-line k)
(define headers
(let loop ([line (read-line)])
(if (end-of-input line)
null
(cons line (loop (read-line))))))
(k request-line headers))

(define (parse-request)
(define (parse-request-line k)
(define request-line (read-request-line))
(k request-line))

(parse-request-line
(cut parse-headers <> do-something)))

Note that I’ve used <a
href=”http://srfi.schemers.org/srfi-26/srfi-26.html”>cut
as a short-cut for lambda.

I’ve got code reuse but the code itself isn’t nice. The
arguments lists were quite a bit longer in the real code and
most of the time arguments are just passed from function to
function without being used (I’ve seen these sort of
arguments called “tramp data”). I also find
that CPSed code can be quite difficult to read — you
have to construct the control flow graph in your head and
then look at the application site to fill in all the
continuations. Ugh.

One way to get rid of tramp data is to use parameters, and this something we talk about in our experience report. However that solution isn’t appropriate here. It forces me to stick with CPS so I can set the parameters in the dynamic extent of the succeeding code, and it extends the lifetime of the values beyond what is strictly necessary. This could be an issue if storing, say, a large request body in a parameter.

Notice that the different versions of
parse-request only differed in which function
they called with the value they computed. If I separate out
the computation of that value, and the decision of which
function to call I can get code reuse without CPS, and I
don’t have long argument lists! This is what my final solution looks like:

;; shared between parse-request and parse-response
(define (parse-headers request-line)
(let loop ([line (read-line)])
(if (end-of-input line)
null
(cons line (loop (read-line))))))

(define (parse-request)
(define (parse-request-line)
(read-request-line))

(do-something (parse-request-line)
(parse-headers)))

(define (parse-response)
(define (parse-response-line)
(read-response-line))

(do-something-different (parse-response-line)
(parse-headers)))

It’s short and sweet, and easy to understand.

So let’s recap what I did:

  • I started with the mutually tail-recursive FSM pattern (that’s a mouthful!)
  • I refactored into continuation-passing style.
  • I separated computation and control, and refactored back to direct style.

So three refactoring (direct style to CPS, separating
computation and control, and CPS to direct style), two of
which are particular to functional languages, and one
pattern. I could do with a better name than
“separating computation and control”. If you’re
aware of some prior work or can think of a better name do
let me know.

Although they use different terminology, the programming
language theory and software engineering communities have
explored a lot of the same ground from different
perspectives. Program transformations are pretty much the
same thing as refactorings, though the former are often
presented in the context of compiler optimisations.<a
href=”http://www.haskell.org/haskellwiki/Research_papers/Functional_pearls”>Functional
Pearls are very similar to design patterns.

If you’re a student of software engineering in functional
languages it is necessary to familiarise yourself with this
literature. This can be difficult. There are no books
summarising this literature, as you’ll find for OO
languages, and the papers are often terse and are not
focused on software engineering. This means they can be
difficult to read if you don’t have a background in
programming languages, and you have to read between the
lines a bit.

Posted in Code | Comments Off on Refactoring Functional Programs