Thursday, January 29, 2009

Reading (reprise)

Well, I decided to start reading Persuasion on the bus this morning, rather than Lilith or Phantastes.

I just have to be honest here: Persuasion is one of my favourite books. I look a bit of a girly-man sitting on the bus reading Austen, I'm sure. But I love her biting sarcasm when she describes Sir Walter and Elizabeth. Or her disdainful mentions of Mrs. Clay's sycophancy. It's word-craft at its finest.

So I am unapologetically reading a chick novel on the bus. And loving it immensely.

Wednesday, January 28, 2009

Hey there

So I'm still here, I just haven't been posting or commenting a lot. I've been caught up in non-blogging pursuits for a while: I'll be back in a bit.

Since my last posting, by bus reading has included Descent into Hell by Charles Williams and The Mythical Man-Month by Fred Brooks. Descent into Hell has long been among my favourite novels, written by one of my favourite authors. A few people have asked me to help them get started reading Charles Williams, I generally lend them the following titles (in this order):

  1. All Hallow's Eve

  2. War in Heaven

  3. Many Dimensions

  4. The Place of the Lion

  5. and Descent into Hell


That's not a complete Chas. Williams anthology, but it gets the essentials across.

I always recommend Descent into Hell last, because I like it best, but I think it's also the most powerful and probably the easiest to misunderstand. I start with All Hallow's Eve because it's the most approachable, and is a great "hook" to get someone into Williams.

Descent into Hell is my one Williams book that's actually a little battered. I cherish each blemish, as they were put on by different people enjoying the book. Not abusing; enjoying. An abused book is a little sad, but a book that's taken a few hits during careful use is a testimony to its quality.

I might need to read Lilith and Phantastes next: it's been a long time.

Friday, January 16, 2009

Breaking out

So like a lot of people, I've dabbled in Lisp programming. Well, "dabble" might not be the right word. I've put significant time and effort into learning both Common Lisp and Scheme; while I've not truly mastered either, I've achieved a certain level of competence.

But the problem with both languages is, how do you take a program written in a language designed to be interactive and package it to be generally useful? It's great that I can start a session with some Common Lisp implementation or another and write some cool code: but in the end, it's not something anyone else is likely to use.

I got around that in Scheme by using Gambit, which allows one to compile Scheme code into C that is then compiled to a native binary. That makes legitimate command-line applications in Scheme that can be feasibly useful to more than just one's self.

But I wanted to try another tack, and decided to try using Lisp as a web-application server. I've tried installing any number of Lisp libraries and frameworks before, with mixed success. After battling for what seemed eternities with ASDF, I'd always give up.

But in some downtime at work and my evenings this week, I finally wrote a simple proof-of-concept AJAX application. It's running on my MacBook Pro, and seems to be working just fine. So I thought it would be fun to try and explain how I got all the parts to work together, in case someone else out there is having the same issues that had almost made me resign Lisp to the "cool but useless" shelf.

It might also be a worthwhile exercise to document this, in case I ever have to start again from scratch. I did rely heavily on "Lisp for the Web" by Adam Petersen (April 2008) in addition to the documentation for each library, framework, and package.

First the application stack. I'm running my little AJAX application on the following frameworks and libraries:

  1. Mac OS X 10.5

  2. Postgresql 8.1

  3. Clozure Common Lisp (used to be OpenMCL)

  4. Hunchentoot webserver

  5. qooxdoo


So my database is PostgreSQL, and I'm using Common Lisp to retrieve that information, package it, and send it to the web browser. qooxdoo handles the browser-end.

Inside Lisp, I'm running several libraries/frameworks/systems to make this chain work. The most prominent are:

  1. Postmodern

  2. CL-JSON

  3. Hunchentoot



And of course I'm doing all this work in Emacs (Aquamacs) and SLIME.

I found one of my toughest problems was getting Lisp libraries and frameworks installed. I've had a lot of trouble with this over the last several years, and I think I finally figured out what the problem is. It's not that I have some oddball Lisp configuration (although OS X + CCL does have some problems), it's that I wasn't paying attention to dependencies. ASDF does some primitive dependency management, but I think I'd been putting a lot more confidence in it than I ought to have. And I found that Lisp libraries generally have poor documentation for their dependencies. So it took me a while to track all this down, but I got there eventually.

One note is, I latched onto CL-PPCRE quite some time ago, and it's been part of my standard Lisp configuration since. So it's possible it is actually a dependency for some of what follows, and I didn't realize it.

The first task is Postmodern. My install steps for Postmodern looked something like this:

(asdf:operate 'asdf:load-op :split-sequence)
(asdf:operate 'asdf:load-op :usocket)
(asdf:operate 'asdf:load-op :md5)
(asdf:operate 'asdf:load-op :closer-mop)
(asdf:operate 'asdf:load-op :ieee-floats)
(asdf:operate 'asdf:load-op :trivial-utf-8)
(asdf:operate 'asdf:load-op :bordeaux-threads)
(asdf:operate 'asdf:load-op :postmodern)

So Postmodern had 7 dependencies I had to apply. After I loaded those libraries (in that order), Postmodern started working.

I actually tried to use CLSQL, but was unable to get it to load due to some UFFI errors. I finally gave up and used Postmodern, which I think is a fine product. The main advantage of CLSQL is wider (not just PostgreSQL) support. If anyone has CLSQL running on OS X plus Clozure, I'd be interested to know how you got it working.

CL-JSON was a lot easier:

(asdf:operate 'asdf:load-op :cl-json)

No dependencies, it just installed lickety-split. Of course, its ease of install was offset by its non-existent documentation. I followed the manual's advice and read the unit tests to figure out how to use it.

After Postmodern and CL-JSON came Hunchentoot. Hunchentoot took some scrounging to get right, but I finally got it going.

(asdf:operate 'asdf:load-op :md5)
(asdf:operate 'asdf:load-op :cl-base64)
(asdf:operate 'asdf:load-op :rfc2388)
(asdf:operate 'asdf:load-op :cl-fad)
(asdf:operate 'asdf:load-op :chunga)
(asdf:operate 'asdf:load-op :url-rewrite)
(asdf:operate 'asdf:load-op :cl-who)
(asdf:operate 'asdf:load-op :babel)
(asdf:operate 'asdf:load-op :alexandria)
(asdf:operate 'asdf:load-op :trivial-features)
(asdf:operate 'asdf:load-op :cffi)
(asdf:operate 'asdf:load-op :cl+ssl)
(asdf:operate 'asdf:load-op :hunchentoot)
(asdf:operate 'asdf:load-op :hunchentoot-test)

13 dependencies! And I'm sure CL-PPCRE is another, but it didn't get listed, as it's in my standard configuration.

In the process, I learned some things about how to organize my Lisp files, and I'm going to share my discoveries with you. My Lisp code is on my MacBook under "/Applications/Lisp". This directory contains two or three Common Lisp implementations, two or three Scheme implementations, and various supporting files and directories. I gathered all the Lisp libraries and frameworks I've downloaded, unzipped them, and put them into a single directory under there called "lib". So that directory now looks something like this:


PeevTop:~ mark$ ls -lh /Applications/Lisp/ | colrm 1 46

MzScheme v352
PLT Scheme v4.1
arc2
asdf
bigloo
bigloo3.1a
ccl
clisp-2.41
lib
sbcl -> sbcl-1.0.19
sbcl-1.0.19
scmxlate
slatex
slime
snow-generic
snow-site
tex2page

Notice there is a directory under there called "asdf". It contains a directory called "registry", which is full of symlinks to the ASD files of all the libraries under "lib":

PeevTop:~ mark$ ls -lh /Applications/Lisp/asdf/registry/ | colrm 1 45

alexandria-tests.asd -> /Applications/Lisp/lib/alexandria/_darcs/pristine/alexandria-tests.asd
alexandria.asd -> /Applications/Lisp/lib/alexandria/_darcs/pristine/alexandria.asd
asdf-install.asd -> /Applications/Lisp/lib/asdf-install/asdf-install/asdf-install.asd
babel-streams.asd -> /Applications/Lisp/lib/babel_0.3.0/babel-streams.asd
babel-tests.asd -> /Applications/Lisp/lib/babel_0.3.0/babel-tests.asd
babel.asd -> /Applications/Lisp/lib/babel_0.3.0/babel.asd
bordeaux-threads.asd -> /Applications/Lisp/lib/bordeaux-threads/bordeaux-threads.asd
cffi-examples.asd -> /Applications/Lisp/lib/cffi_0.10.3/cffi-examples.asd
cffi-grovel.asd -> /Applications/Lisp/lib/cffi_0.10.3/cffi-grovel.asd
cffi-tests.asd -> /Applications/Lisp/lib/cffi_0.10.3/cffi-tests.asd
cffi-uffi-compat.asd -> /Applications/Lisp/lib/cffi_0.10.3/cffi-uffi-compat.asd
cffi.asd -> /Applications/Lisp/lib/cffi_0.10.3/cffi.asd
chunga.asd -> /Applications/Lisp/lib/chunga-0.4.3/chunga.asd
cl+ssl.asd -> /Applications/Lisp/lib/cl+ssl-2008-11-04/cl+ssl.asd
cl-base64.asd -> /Applications/Lisp/lib/cl-base64-3.3.2/cl-base64.asd
cl-fad.asd -> /Applications/Lisp/lib/cl-fad-0.6.2/cl-fad.asd
cl-json.asd -> /Applications/Lisp/lib/cl-json/_darcs/pristine/cl-json.asd
cl-postgres.asd -> /Applications/Lisp/lib/postmodern-1.01/cl-postgres.asd
cl-ppcre-test.asd -> /Applications/Lisp/lib/cl-ppcre-1.3.0/cl-ppcre-test.asd
cl-ppcre.asd -> /Applications/Lisp/lib/cl-ppcre-1.3.0/cl-ppcre.asd
cl-who.asd -> /Applications/Lisp/lib/cl-who-0.11.1/cl-who.asd
closer-mop.asd -> /Applications/Lisp/lib/closer-mop_0.55/closer-mop.asd
clsql-aodbc.asd -> /Applications/Lisp/lib/clsql-4.0.3/clsql-aodbc.asd
clsql-db2.asd -> /Applications/Lisp/lib/clsql-4.0.3/clsql-db2.asd
clsql-mysql.asd -> /Applications/Lisp/lib/clsql-4.0.3/clsql-mysql.asd
clsql-odbc.asd -> /Applications/Lisp/lib/clsql-4.0.3/clsql-odbc.asd
clsql-oracle.asd -> /Applications/Lisp/lib/clsql-4.0.3/clsql-oracle.asd
clsql-postgresql-socket.asd -> /Applications/Lisp/lib/clsql-4.0.3/clsql-postgresql-socket.asd
clsql-postgresql.asd -> /Applications/Lisp/lib/clsql-4.0.3/clsql-postgresql.asd
clsql-sqlite.asd -> /Applications/Lisp/lib/clsql-4.0.3/clsql-sqlite.asd
clsql-sqlite3.asd -> /Applications/Lisp/lib/clsql-4.0.3/clsql-sqlite3.asd
clsql-tests.asd -> /Applications/Lisp/lib/clsql-4.0.3/clsql-tests.asd
clsql-uffi.asd -> /Applications/Lisp/lib/clsql-4.0.3/clsql-uffi.asd
clsql.asd -> /Applications/Lisp/lib/clsql-4.0.3/clsql.asd
dcm.asd -> /Applications/Lisp/lib/elephant/_darcs/pristine/src/contrib/rread/dcm/dcm.asd
flexi-streams.asd -> /Applications/Lisp/lib/flexi-streams-1.0.5/flexi-streams.asd
gzip-stream.asd -> /Applications/Lisp/lib/gzip-stream/_darcs/pristine/gzip-stream.asd
hunchentoot-test.asd -> /Applications/Lisp/lib/hunchentoot-0.15.7/hunchentoot-test.asd
hunchentoot.asd -> /Applications/Lisp/lib/hunchentoot-0.15.7/hunchentoot.asd
ieee-floats.asd -> /Applications/Lisp/lib/ieee-floats/ieee-floats.asd
lml-tests.asd -> /Applications/Lisp/lib/lml-2.5.7/lml-tests.asd
lml.asd -> /Applications/Lisp/lib/lml-2.5.7/lml.asd
md5.asd -> /Applications/Lisp/lib/md5-1.8.5/md5.asd
parenscript.asd -> /Applications/Lisp/lib/parenscript-20071104/parenscript.asd
...

So now all the ASDF packages I have on my system can be installed from "/Applications/Lisp/asdf/registry/".

Similarly, the packages I've written are in a registry under "~/Documents/Code/Lisp/asdf-registry". So my Lisp init file contains this:


#+:asdf (pushnew "/Applications/Lisp/asdf/registry/"
asdf:*central-registry*
:test #'equal)
#+:asdf (pushnew "/Users/mark/Documents/Code/Lisp/asdf-registry/"
asdf:*central-registry*
:test #'equal)


And now all the Lisp software that's either a dependency or tool I've gotten online or software I've written myself can be loaded into the Lisp environment without having to mess around and find it. This little piece of organization helped tremendously in getting this system working.

So once all this was installed, I was suddenly able to fire up Hunchentoot and serve out "pages". I used the default test pages for a while, then decided to get down to business.

Sunday, January 11, 2009

The Best of Intentions

We have progressively abandoned that freedom in economic affairs without which personal and political freedom has never existed in the past. (The Road to Serfdom, p. 13)


I've been working on Hayek's The Road to Serfdom (The University of Chicago Press, 1944). Hayek wrote it in the 40s, before the end of WWII. It's a book by an Austrian in the USA, an analysis of totalitarianism in a time when three totalitarian regimes more or less owned Europe.


The Road to Serfdom is too intricate a book to intelligently review on a blog. I wish I could, but it's simply too complex to tackle in this forum. It's partly political, partly economical: it's a book with a simple message, but it's not a simple book. The book's message is this: socialism is merely a return to feudalism. I'll limit this "review" to a few comments on the book and its thesis.


Hayek's arguments are largely illustrated by the three collectivist regimes in Europe in his time: Soviet Russia under Stalin, National Socialist Germany under Hitler, and Fascist Italy under Mussolini. But while they provide excellent illustrations for him, his argument is not really against them particularly. His argument is against collectivism (and particularly socialism) in principle. His argument is that socialism logically leads to the abuses of those regimes, that they were merely acting out the very same principles espoused by American and English "progressives" of his day. And if the proof of a theory lies in its ability to predict the future, Hayek's been vindicated in the 60 years since.


Hayek's analysis of Nazism and Fascism as what we would term "left-wing" phenomena is refreshing after countless inane pop-wisdom references to them as "extreme right-wing" philosophies. It's obvious that a political party that comes to power on the popular vote advocating government seizure of factories and businesses, offering socialized health care and retirement planning, and heavily taxing "unearned income" (to the tune of about 90% on capital gains and estate taxes) must be considered to have more in common with what we now call "the left" in North America than "the right." Aside from genocide (and I haven't personally met any genocidal conservatives), the Nazi political platform sounds like the NDP in Canada or the Democrats here in the USA. Mussolini's Fascism was also the " working man's party" in Italy.


It is important to note that what Hayek calls "liberalism" we call "conservativism" today. That is, he uses the term "liberal" in the sense of Jane Austen, not in the sense of Hilary Clinton. He refers to the laissez-faire capitalists as "liberal" in contrast to the socialistic "progressives".


Hayek makes the interesting claim that the only economic system that's ever been shown to increase personal freedom is capitalism, which brought an end to feudalism in Europe and led to the Magna Carta in England and constitutional democracies in America. Try as I might, I can't come up with a counter-example. His proverb that "socialism is slavery" is borne out in history, so far as I have been able to tell.

Hayek's argument might well be summarized as this: socialism is really just a return to feudlism. Feudalism was essentially a state of affairs where the Crown owned the land, and rule over it was delegated through levels of nobility that governed those living on it. Socialism offers fundamentally the same dynamic, where a totalitarian government owns (or at least controls exclusively) all property, and that control is delegated downwards in various levels of the government. The effect on the common individual is the same: nothing is his, and all decisions are made for him.

There are some differences: for example, feudalism was perpetuated by landed aristocracies, where socialist regimes generally perpetuate through political parties. But in actual practice, feudalism in mediaeval Europe might have been a significantly better system for the "common man" than the socialist regimes we've seen in the 20th Century. The mediaeval feudalism was restrained by a vague religiousness (despite flagrant hypocrisies) that at least theoretically believed in the sacred worth of the individual, where modern collectivist regimes have been virtually unrestrained. Mediaevals launched the Crusades, but they were child's play compared to the killing fields of Cambodia or the gulags of the Soviet Union. And however imperialistic the Crusades were, modern Socialists have perpetuated atrocities on their own people ("citizen" is really a euphemism) that the Mediaevals reserved for foreigners and "infidels."

Hayek's central argument is that the totalitarianism of Nazi Germany or the Soviet Union were not anomolies: totalitarianism is the expected outcome of a collectivist society. A socialist country cannot thrive without totalitarianism, and attempts to have the one without the other are unstable: either the country must abandon its collectivism, or it must abandon individual freedom.

Individual freedom must have the effect of upsetting attempts at central planning: they cannot reasonably coexist. Nazi Germany, Fascist Italy, and Soviet Russia were merely the logical outworkings of Socialist principles.
We must now examine the belief from which man who regard the advent of totalitarianism as inevitable derive consolation and which seriously weakens the resistance of many others who would oppose it with all their might if they fully apprehended its nature. It is the belief that the most repellent features of the totalitarian regimes are due to the historical accident that they were established by groups of blackguards and thugs. (p. 134)

The "thuggish" nature of these countries was not due to the historical accident that the thugs in them latched onto Socialism, but that Socialism cannot exist without significant coercive force from the government. A government where wealth is distributed equally is a government that treats its people unequally: since it is a plain fact that all are not capable of producing equally, any arrangement in which all have similar wealth is evidence that those most capable of producing are being unequally penalized for their abilities. A situation where the only possible employment is from a single source (whether the government or a monopoly) is by definition a state of slavery. Slavery is not unemployment, slavery is having no choice in one's vocation.


The worst of reading Hayek is the knowledge that warning was already too late in the 40s. There is really very little chance anything will change now. Here are just a few points to consider:

  • We condemn Hitler's eugenics, but every pregnant woman is encouraged to test for potential birth defects during pregnancy, so she can decide whether to abort. How is this not just eugenics?

  • It is possible to be self-employed, but government and society both view that arrangement with suspicion. And here in the USA, there are serious tax consequences for the self-employed. The system is built to restrict individual aspiration and effort, and to channel people into regulated employment.

  • And "privacy" is a joke in a society where I have to report to the government to the nearest dollar how much I earn yearly.


I don't see anything but acceleration towards totalitarianism in the future here. Our totalitarianism is "soft" compared to Hitler's, but it's no less real.

For all you northerners...

a brief introduction to barbecue---the original Southern art form.