Introduction

Lately I've been fooling around with Lisps. I've done some work on Linux in SBCL, an open source Common Lisp implementation that seems like a good, solid piece of code. But I've spent most of my time writing code in L#, an interpreted Lisp dialect for the .Net CLR. Lots of people are familiar with Common Lisp, but not all that many people seem to be familiar with L# yet, so I thought I would share my first impressions.

Like apparently everyone else who has started learning Lisp in the last five years, I got interested by reading Paul Graham. In particular, I didn't like the idea of programming in Blub without knowing more about some of the available alternatives.

So I've read Peter Seibel's Practical Common Lisp and I've started reading Paul Graham's On Lisp, and trying to learn how Lisp works.

Of course, if you keep reading Paul Graham, you also notice that he doesn't exactly endorse Common Lisp. He's been working on a newer, sexier Lisp called Arc, which of course you can't use yet. In particular, he argues the importance of having powerful, modern libraries.

It was somewhere around then that I ran across L#. L# was designed by Rob Blackwell with a lot of Graham's published ideas for Arc in mind. To me, at least, the language looks a little cleaner. In addition, it's designed to run on top of .Net, which means that even in its early stages, it comes with complete with a massive set of libraries for everything from XML to database access to user interfaces. When you add in the fact that I'm employed as a C# developer, so I already know those libraries pretty well, L# seemed like a no brainer to try out. So naturally, I did.

There's a lot to like about L#

If you're still with me at all, you're probably ready for me to move past the preamble and actually talk about L#. So here we go.

The single best thing about L# is exactly what you would expect: it combines a Lispy (and very clean) syntax with the massive library support of .Net. Want to do regular expressions? There's a .Net library that does all the heavy lifting. Hate all the gratuitous verbosity you get in .Net? Write a 5-line wrapper function and go to town.

Here's a really simple but real-life example: if L# comes with a concatenation operator, I haven't found it yet. I was doing a whole lot of string concatenation operations, and wanted an easy way to do it. In C# there are two basic ways to do string concatenation. The expensive way with clean syntax is to do:

mystring = foo + bar + baz + "

";

which instantiates a new string for each concatenation operation. Meanwhile the efficent way with heinous syntax is to use a StringBuilder, which has a buffer so you don't have to reallocate space every time:

StringBuilder sb = new StringBuilder(); sb.Append(foo); sb.Append(bar); sb.Append(baz); sb.Append("

"); mystring = sb.ToString();

You could encapsulate a function for doing this, of course, and end up with something like:

string[] myarray = { foo, bar, baz, "

" }; string mystring = MyStringLibrary.Concatenate(myarray);

That's a little better, but it's still kind of an eyesore. You can't declare the array inline as an argument to the function, and you have to carry around a class to hold the function name.

It won't surprise anyone familiar with Lisp, but L# makes it easy to make it easy. Here's my simple function to concatenate a list. I expect a Lisp guru could do something cooler, but I'm nowhere near a Lisp guru yet:

(= concat (fn (&rest members) (let sb (new system.text.stringbuilder) (foreach elem members (call append sb elem)) (tostring sb))))

This yields a nice clean syntax for string concatenation, with all the advantages of the efficient, ugly way in C#, and a syntax as simple as adding strings together:

(concat foo bar baz "

")

Actually, I seem to be using string concatenation enough that I think I'm going to rename the function ct , which should make things even more terse.

So anyway, that's just the simplest, scratch-the-surface example. Once you get into macros and things like that, I'm pretty sure that the differences will be even more dramatic.

L# shows enormous potential as a glue language for .Net applications: scripting, configuration, things like that. For scripting tasks, you can easily write simple, terse scripts that work with the code you've already built. I feel a little silly recommending a variant of possibly the most powerful programming languages ever devised as a way of scripting something written in C#, but it's a good way to get a foot in the door and add L# to your toolchain.

Steve Yegge has made a pretty compelling case for Lisp as a replacement for XML in things like config files and logs. I don't have much to add to that, but if you've ever gotten tired of messing around with XSLT transforms, L# offers an easy way to abandon them forever.

So utility programming in L# is pretty cool, but can you do more than that? Can you write real apps? I don't know yet. But I plan to find out. A language that's really powerful, but still fundamentally easy and fun to work with is worth experimenting with to find out how far you can take it.

I'm sure I won't be able to rip out years of production code and replace them all with L# -- really, I wouldn't want to, even if I could. But there's no reason not to look at it for new projects and interoperation. Currently, there's a few missing pieces for seamless interoperation with other .Net languages (mainly, L# doesn't compile into callable assemblies yet), but there's nothing standing in the way of getting those problems solved except time and effort.

L# Tools

The current tools for developing in L# aren't everything you could want, but they're not bad. First off, you can use Visual Studio, but there are no direct integration tools yet. Even without syntax highlighting, etc., this is still a pretty good solution. The main reason it works pretty well, is that it gives you the ability to debug your code. Well, sort of.

Actually, what you can do is load the C# source code for the LSharp interpreter into Visual Studio and debug the interpreter. You set breakpoints in places like Eval() and Call() and follow your code as it evaluates. This took a little adjusting to, but it actually works pretty well. You can drill down and see exactly what it's evaluating and how it's failing. Did you forget to quote something and send an unquoted symbol by mistake? It's all right there in the interpreter -- you can see what it's doing with your code.

Outside the debugger, the main advantage of using Visual Studio is that if you're integrating it with C# in the same solution, you can manage all the files in the same place. But really, to Visual Studio your L# files are just opaque text files.

Another tool I've worked with is TextPad, which is a feature-rich text editor for Windows that I use anyway. There's a syntax file for L# for TextPad, so it gives you syntax highlighting and parentheses matching (with ctrl-M ). I often edit L# files in TextPad at the same time that I have the project open in Visual Studio, and Visual Studio has a handy reload dialog that pops up when files have changed.

There are other tools for working in C#, but I haven't had a chance to put them through their paces yet. xacc.ide is an integrated development environment being built that not only has support for L# syntax, it apparently uses L# as a scripting language. That certainly implies that xacc.ide will be a good tool for L# development. Finally, emacs support for L# has been developed, so if you're comfortable working in emacs, that may be just the ticket.

Conclusion

Of course, not everything in L# is ideal. I've run across some annoyances as I've been working in L#, as you would imagine for a young language. Nothing that is a showstopper, but a few things I wish worked a little better. The main thing, though, is that I haven't run into anything that has made me even want to consider abandoning L# for another language.

I'm hopeful that at least most of the annoyances can simply be fixed, so I'm going to write a followup post that goes into these in more detail, along with some ideas about what to do about them. This post is long enough as it is.

In the meantime, I hope this helps people know more about what to expect with L#, and I hope that people will go ahead and try it out. It's a solid language, and it potentially adds a whole new dimension to .Net projects.

Tags: .Net, L#, LSharp, Lisp, C#