Friday, September 18, 2009

Lisp Outside the Box

Nick Levine has posted the first batch of sample chapters (Chapters 13–16) from his book-in-progress Lisp Outside the Box, which is being published by O'Reilly. My understanding of the book's purpose is that it's intended to be an introduction to Lisp crafted specifically to show that Lisp is applicable to a wide range of problems and that extensions and external libraries extend its application domain outside of what's provided “inside the box.”

With that understanding in hand and recognizing that we are looking at only a small sliver of the book, largely without context, it is worth while taking a look at the chapters and seeing how well they live up to their stated goals. The weakest chapters, in my opinion, are 13 and 14. These two chapters are devoted to a pretty thorough look at AllegroCache, the proprietary persistent object database that comes with Allegro Common Lisp (ACL) from Franz Inc. The question is: Are these chapters useful to someone learning Lisp? They do, it's true, introduce new Lispers to the notion of persistent objects, but in a way that's not apt to be useful to them. Not useful because someone who is new to Lisp and wants to experiment with it is unlikely to be using ACL. Yes, Franz provides a free (but crippled) version of ACL that includes (an even more crippled) version of AllegroCache, but why would a casual usual bother when there are free, industrial strength implementations such as SBCL and Clozure available? An academic license for ACL Professional starts at $599 and versions that can be used to produce commercial code cost much more. In other words, the most likely user of ACL is a professional Lisp developer who is using a version of ACL provided by his employer, not someone trying to learn about Lisp and its capabilities.

At the end of Chapter 14, the author devotes about a page to Rucksack and Elephant, two open source alternatives to AllegroCache. Rather than devote two chapters out of 32 to a proprietary solution that the intended reader is not apt to be using, it would have made more sense to devote those chapters to Rucksack and Elephant and mention AllegroCache as a commercial (and perhaps better) solution to the same problem.

Chapter 15 deals with concurrency. The author repeats the mistake of the previous two chapters by using ACL as his primary example, but here, at least, the sample code easily translates to other implementations. My main complaint about this chapter is that the author uses the term process to describe what everyone else calls threads. He does this because it's the traditional terminology in the Lisp community, and perhaps he has a point, but I think it's a disservice to the new Lisper because it uses process to mean something different from what it means everywhere else. Indeed, in most contemporary writing about Lisp you see the term thread used when discussing the concept that he calls process. Other than these two nits, the chapter is well written and should be helpful to someone trying to learn to use Lisp in the real world.

The last chapter, on garbage collection and memory management, is the strongest. The main lesson here is to trust the garbage collector. In almost every case the beginning Lisper is likely to encounter, it's better to let Lisp handle memory management rather than trying to hand optimize it by using, for example, the destructive versions of commands. The chapter provides a nice, elementary explanation of how garbage collection works and mentions some things to watch out for, such as creating memory leaks by inadvertently maintaining pointers to old data.

All in all this appears to be an interesting and worthwhile book that can help the new Lisper become familiar with the parts of Lisp that1 aren't mentioned in the Common Lisp Specification. The problem, of course, is that these parts are not standardized and thus are implemented differently in different Common Lisps. By considering several Common Lisps, the author shows the reader the various ways these important but nonstandard parts of Lisp are implemented. I do think, however, that it would improve the book to take the majority of the examples from Lisps that a new user is actually apt to be using.

Tuesday, September 15, 2009

Yet Another “No Parenthesis Lisp”

I really don't understand this. It's bad enough that noobs keep coming up with stuff like this, do we have to advertise their silliness on the Lisp Aggregators? If you want Python, go use Python already.

Saturday, September 12, 2009

Thursday, September 10, 2009

Org Mode and the iPhone

Over at the Org Mode Mailing list, Richard Moreland has a post about a prototype iPhone app for Org Mode. It basically provides an off-line interface to Org Mode that allows viewing of Org files and has a capture facility so that you can make notes for later import into Org. He and Carsten Dominik are still working on the app, which is not yet even at the beta stage, but they do have a teaser video of it running in the iPhone simulator.

I can't wait to get my hands on it. As I've mentioned before, I'm a big fan of Org Mode and use it to plan and run my life. One of the missing pieces has been a way to take notes or capture a TODO on the run. This new app will be much more convenient than emailing myself a note or capturing it on the iPhone note pad.

By the way, if you're an Emacs user and aren't using Org Mode you owe it to yourself to give it a try. If you aren't an Emacs user you may find that Org Mode is a sufficient reason to become one.

Tuesday, September 8, 2009

Continuation Patterns

What makes Scheme Scheme? Any list of features purporting to answer that question would surely include

  • lexical scoping,
  • tail recursion, and
  • first class continuations

The first two are familiar to all Lisp programmers and are also features of Common Lisp either as part of the language definition (lexical scoping) or as a practical matter (tail recursion). Continuations are less well understood but are one of the features that make Scheme so powerful. They represent, to my mind, the epitome of the familiar Scheme mantra that languages are made powerful not by piling on features, but by removing weaknesses and restrictions that make the new features seem necessary.

As a practical application of this principle, consider exceptions: Scheme doesn't have any (at least prior to R6RS), but they are easily implemented with continuations. That's a facile statement, of course, but it doesn't rise to the level of "Scheme is Turing complete so …" Instead, it should be understood in the sense that one can easily write an exception library using continuations without needing to make changes to the Scheme compiler or interpreter. Rather than imposing a single exception handling mechanism on all users, Scheme allows each user to define one suited specifically to his or her needs. Here's a nice example from Dan Friedman, Chris Haynes, and Kent Dybvig that shows how easily this can be done.

The problem, as I hinted above, is that continuations are tricky to understand and as a result aren't understood at all by many Scheme programmers. I just stumbled across an old (2001) paper by Darrell Ferguson and Dwight Deugo that might help. They begin by explaining continuations in terms of contexts and escape procedures. To be sure, this is a conceptual definition that may or may not have anything to do with an actual implementation, but it does serve to help beginning Scheme programmers get their heads around the notion of continuations.

The meat of the paper is an examination of several continuations usage patterns. They begin with showing how to use continuations to escape from a loop and discuss why this technique can be preferable to the usual naive method of setting an "end" value that gets checked each time through the loop. From there they move on to the related pattern of breaking out of a recursion discarding any partial results that have been built up.

Next they consider control structures by showing how to implement a loop with continuations and how to escape from and then reenter into a recursion. Finally, they consider the more complicated patterns that implement coroutines, non-blind backtracking, and multitasking.

This is a useful paper for someone who is looking for examples of how call/cc can be used to solve real problems. Unless you're completely familiar and comfortable with continuations, it's definitely worth a read.