Dan McKinley
Math, Programming, and Minority Reports

@mcfunley.com

Wheels I Have Reinvented
September 3rd, 2006

This site has been silent for quite a while. My lame excuse for this is as follows.

Sometime around the beginning of the summer I started trying to learn functional programming in earnest. I had some exposure to this in school (ML, if I remember correctly), but not nearly enough, as it turns out. C#’s anonymous methods provided the “eureka” moment that made me want to revisit the topic. I had also been asked to contribute to The Hub, but I had felt like I was lost in the world of F# and that fizzled out altogether (maybe now I might have a few things to say).

So that’s my story—I have been exploring strange new(-ish) topics and I’ve found that I haven’t had anything insightful to contribute to the world.

Recently I’ve been trying to complete a few large projects in Common Lisp. I’m pleasantly surprised to find myself saying that most or all of the highfalutin crap that is spouted about Lisp is true. As to why it isn’t the most-used language in the world right now, I am too much of a novice to speculate. But purely from a language standpoint it is certainly making all of the others feel, well, tedious.

Lisp seems to supersede every single neat trick I have ever come up with programming professionally. It either contains them outright, or it makes them trivial through macros or completely unnecessary for some other reason. Let me give you one simple example.

Writing applications in C#, I’ve occasionally had a singleton or some kind of global object that I wanted to be redefined within a certain call stack. Let’s say I have this API:

class Foo
{
    public static Foo Default { get; }
}

And I want this to be redefined for a little while while I call some method called Bar(). Impersonation of users is one concrete example of where this is useful.

My neat-trick solution to this problem is to make the implementation of Default use thread local storage (and maybe fall back on a static instance too), then create a “scope” class that allows me to write code that looks like this:

// Original value of SomeOtherFoo out here
using(FooScope s = new FooScope(someOtherFoo))
{
    // In here, Foo.Default gives someOtherFoo
    Bar();
}
// Original value of SomeOtherFoo out here

(I am skipping over a lot of irritating details here and let me be clear, I don’t claim to have invented this. I just mean that I burned a lot of hours arriving at it basically independently of the ten million other programmers who probably recognized the same need and did the same thing. It is purely my own ignorance and stupidity that made “re-discovering” it necessary.)

Anyway, I thought that was clever at the time. But with dynamic scope (as opposed to global scope, which is what static fields have in C#) Lisp has this as part of the language. Writing this:

(let ((*default-foo* some-other-foo))
    (bar))

Is basically the same thing with no effort. The Lisp syntax has the added advantage of working with objects other than the ones I author myself.

This reminds me of the first time I was exposed to .NET events. I realized that I had implemented the same god-damned thing in other languages a handful of times (albeit as a less-seasoned programmer) and it never worked as beautifully or as simply.

Naturally, CLOS seems to have some features that I now realize I have been mimicking imperfectly with events. It also has features that will probably replace events in many of the problems where I have applied them. That is an altogether different story.

Back home