clojure is the best lisp yet

I've dabbled in a few lisp dialects, but I generally become frustrated with some deficiency or other. I had been holding out some hope for Paul Graham's arc, but when I tried it out, I wasn't exactly blown away.

Common Lisp has a rather bloated library of functions, many with disgustingly long names. Arc has indeed successfully addressed this problem, and so has clojure: the longest function name I could find in Clojure's succinct and powerful library was the outlier "clear-agent-errors".

Lisp is old enough that many dialects have trouble with modern character encodings. Arc doesn't support anything but ASCII (so far anyway), and although elisp does it seems to regard UTF-8 with suspicion. Clojure supports UTF-8 out of the box, even inlined in your source code.

Many lisps have a shocking shortage of useful library modules for common tasks, especially related to networking or particular file formats, when compared to Perl, Python, etc., and creating bindings for existing C or other native libraries can be pretty tricky. Clojure allows you to directly use any part of any existing Java library, no special bindings needed.

With a large variety of libraries comes name collisions. Arc apparently hasn't addressed this problem yet, while clojure has all the namespace support you'll need.

JavaScript and other modern languages have demonstrated to me the power of hashes and the utility of being able to easily initialize them with literals in my code, yet few lisps make this convenient. Clojure has rich support for sorted maps, hash maps, and struct maps (which allow you to efficiently store a large number of hashs with common keys), including succinct syntax for creating new ones.

Besides cleaning up some of lisp's historic weaknesses, clojure provides several innovative new features. For example, the idea of data structure interfaces allows you to write code that can work the same on a variety of concrete types. The (conj ...) function adds an item to a collection, whether that collection is a list, a vector, or a hash.

I also found it interesting that Clojure's built in data structures are all immutable. The API makes working with these convenient, and should allow you to avoid common hassles when dealing with concurrency.

There are many other little details that clojure seems to have tweaked for the better compared to older lisps. The syntax for defining macros is a little tidier, (cond... ) is a bit more succinct, and it even has support for literal regular expressions.

I don't know that many lisps, and none of them very deeply. But for what it's worth, clojure is my favorite.


experimenting with vnc

My home setup consists of a server in the basement with thin clients in the upstairs office. I love this setup because it means the office is entirely solid state; no fans or disks to make noise. It's the ultimate silent PC.

Method 1: XDMCP

I typically don't run applications on the thin clients, rather I run an X server with -broadcast to get an XDMCP session from my server. From that point on, everything (gnome, window manager, browser, xterms, etc.) runs on the server with $DISPLAY pointing at the thin client. This is pretty simple to set up, just change gdm.conf on the server:

--- gdm.conf.dpkg-dist  2007-05-29 05:08:37.000000000 -0400
+++ gdm.conf    2008-02-07 09:56:42.000000000 -0500
@@ -59,2 +59,3 @@
@@ -74,2 +75,3 @@

and on the thin client, in /etc/rc.local:

X -broadcast

Method 2: VNC

Running X remotely, even on a 100 Mbit network, can get slow. In particular, Firefox just crawls. Making a new tab (blank page), chug chug. Rendering pages, chug chug. It's plenty usable, and you can get used to it, but it's a shock to go back to a normal PC and see the speedup that local rendering buys. (Xterms, btw, are plenty fast on remote X because they're just sending characters to the server, which it then renders locally.)

So I started experimenting with VNC. To my delight, VNC restores Firefox's rendering speed. In fact, VNC is fast all around. I see some very minor latency in my xterms since they're now sending graphics over the link instead of characters, but it's barely a price to pay for the overall speedup.

Here's what I did to make this work. First the server, I install apt-get install vnc4server, then create three entries in inetd.conf to correspond to the screens I have attached to the thin clients:

server # cat >> /etc/inetd.conf <<EOF
5910 stream tcp nowait nobody /usr/bin/Xvnc4 Xvnc4 -inetd \
  -depth 24 -geometry 1024x768 -fp tcp/oliva:7100 \
  -query localhost -once -securitytypes none
5912 stream tcp nowait nobody /usr/bin/Xvnc4 Xvnc4 -inetd \
  -depth 24 -geometry 1280x1024 -dpi 85 -fp tcp/oliva:7100 \
  -query localhost -once -securitytypes none
5919 stream tcp nowait nobody /usr/bin/Xvnc4 Xvnc4 -inetd \
  -depth 24 -geometry 1920x1200 -dpi 93 -fp tcp/oliva:7100 \
  -query localhost -once -securitytypes none
server # /etc/init.d/openbsd-inetd restart

On the thin client I apt-get install xvnc4viewer, then replace the -broadcast line in /etc/rc.local with:

# this corresponds to the 1920x1200 entry, suitable for a 24" LCD
xinit /usr/bin/xvnc4viewer -fullcolor -fullscreen server:5919

Still investigating...

Not everything is perfect using VNC. Here are a few problems I've run into:

A community blog by the members of n01se.net

May 2006 / June 2006 / July 2006 / October 2006 / February 2007 / May 2007 / July 2007 / February 2008 / March 2008 / May 2008 /

Powered by Blogger