On Scheme

Thoughts on Scheme and teaching Scheme

Archive for the ‘Scheme Community’ Category

Convincing Programmers They Want To Use Lisp

Posted by Peter on April 7, 2006

A reader commented yesterday that one, unmentioned, barrier to the adoption of Lisp as a universal language is convincing programmers of other languages that Lisp is a better choice. Its hard enough to convince someone to move from one language to another when they look the similar, for example from C to C++, so convincing someone that they want to use Lisp is even harder than normal.

Everyone says how elegant Lisp syntax is and how useful functional programming is. This may be true but it is definitely not convincing to the experienced programmer. The experienced programmer is not intimidated by complicated code, which can have its own kind of elegance, what they want is safety, readability, and extensibility.

For example you may, badly, try to convince them that Lisp is better by showing them how a universal map function is easier to write.
Your example may look like the following:

(define map
  (lambda (function first rest combine list)
    (if (null? list)
        '()
        (combine (function (first list)) (my-map function first rest combine (rest list))))))

You point out the elegance of this, how its operation is extendable to any kind of data structure, for example it can be called on lists as follows: (map (lambda (x) (+ 1 x)) car cdr cons '(1 2 6 7)), and expect the beauty of first order functions to win the programmer over.

However the programmer responds with the following:

interface ConCell<T>
	{
	public T car();
	public ConsCell<T> cdr();
	static public ConsCell<T> cons(T a, ConsCell<T> b);
	}

interface ElementFunction<A, B>
	{
	static public A operate(B x);
 	}

class Map<A, B>
	{
	public static ConsCell<A> doMap(ElementFunction<A, B> func, ConsCell<B> list)
		{
		if (list)
			{
			return ConsCell<A>.cons(func.operate(list.car()), Map<A, B>.doMap(func, list.cdr()));
			}
		else
			{
			return null;
			}
		}
}

Yes, the definition is much longer, but it can be called in the same basic way: Map<int, int>.doMap(myAdditionFuncion, NumList.MakeList(1, 2, 6, 7));. The experienced programmer doesn’t care that the definition is substantially longer, since they can use it in their code in basically the same way. In fact they may prefer their definition because it is both type safe and extendable. For example if you wanted every member of the data structure to implement an index function you could add public int index(); to the cons cell definition, and either force structures to implement it or throw an exception. Yes the same extensibility, and possibly type safety as well, could be accomplished in Lisp using an object system, but then your definition of map is not much shorter or more elegant than theirs.

Now that I have demonstrated the wrong way of doing things what is the right way? The right way is to show them macros. Give the example of a networked file system, where when you open a remote file you send the in use message, and when you close it you send the finished message. Thus in the code you will see a lot of the following pattern:

SendInUseCommand(f);
…
SendClosedCommand(f);

All it takes is to forget to send the closed notification once and you have a hard to find bug on your hands. The experienced programmer knows that while they may always remember to do this, since they wrote the system, their colleagues may not. Now show them the following macro:

(defmacro with-net-file
  (lambda (file &rest body)
    `(progn (OpenNetFile file) ,@body (CloseNetFile file))))

Now to write their network file operations you write:

(with-net-file f
   …)

And now no one can forget to close the file, plus it’s shorter as well. There is no way to do this in a non Lisp language. The closest you can come is to create an object whose constructor sends the open command and destructor sends the closed command, but even this approach has problems. Languages such as Java don’t have reliable destructors, so this option is flat out for them. In other languages you can either create the object on the stack, which means that the file will be in use for the entire function call, which is definitely not desirable (maybe a function called within it wants to open the same file, and you only needed the file for the very beginning of the function), but the only other alternative is to dynamically create and destroy the object when you need it which has the same problem, the programmer needs to remember to dynamically destroy it.

Once you have caught the programmer’s interest with simple macros show them some other cool things they can do, like language extensions. Experienced programmers are always looking for more control, and macros give it to them. Later you can tell them that functional programming is cool too, but they probably won’t need that incentive.

On a personal note macros are what convinced me to move to Lisp. For the longest time I was a C++ programmer. Even though I had seen some Scheme and Lisp back in school it never grabbed me, probably because they didn’t mention macros. However once I read On Lisp, and saw how cool macros were I was hooked. Why I ended up favoring Scheme, with its ugly and complicated macro system instead of Common Lisp is a story for another day however.

Posted in Common Lisp, Scheme Community, Teaching Scheme | 29 Comments »

Why Isn’t Everyone Using Lisp?

Posted by Peter on April 6, 2006

You know Lisp* is great, I know Lisp is great, so why isn’t everyone using Lisp? A long time ago people might have shied away from Lisp claiming that it is too slow to be practical, but after Java took off I think we can all see that the speed of a language is not too closely correlated with its success.

I think that Lisp basically has three problems that prevent it from becoming mainstream. One is the lack of libraries, specifically libraries that handle web functionality. I know that there are many many libraries for different implementations of Lisp, and that you can do web programming in Lisp, but there is no one standardized and accepted solution to this problem. Different libraries work under different implementations of Lisp, and provide different kinds of functionality. Compare this to languages such as Python, Ruby, and Java, which have a standard ways of handling networking and the web and you can see why developers might think that Lisp is somewhat lacking in this area.

Another major problem with Lisp is its number of dialects. In one sense having a large number of dialects is a strength because it allows innovation. However because of this it is hard to find programmers who are all proficient in a single dialect, are competent, and who want to work for your business. This makes Lisp somewhat unattractive to a company who would rather be sure of having a mediocre Java team than risk not having a Lisp team, no matter how great its potential. Also, in a project with multiple programmers dialect dependant details such as how the module system is implemented, what kind of objects you are using, ect become rather important, which is why a PLT Scheme programmer can’t simply start working in Common Lisp the next day.

Finally Lisp lacks a good IDE. Yes I know many of you favor emacs, and I won’t deny that emacs has its strengths, but for a corporate environment an IDE such as Eclipse or Visual Studio is important. Such IDEs provide graphical representations of code and package structure that allow developers to easily navigate through code created by other people. Additionally it is easy to standardize on an IDE such as these, as anyone can use them with only a few minutes of instruction, unlike emacs which only exposes its powerful features to the experienced and gifted.

Obviously I wouldn’t advocate a solution to these problems that involves trying to standardize all the dialects into one language. That has already been tried with Common Lisp, and Common Lisp failed to do away with the competing dialects, and unfortunately has become stagnant as a language, with new features being added only rarely. What we really need is a set of inter-dialect guidelines, which the community actually likes and thus will implement universally. Such guidelines would need to dictate such things as how modules are declared, if dialects are lisp-1 or lisp-2, and the C foreign function interface (to allow easy porting of libraries). Obviously such a task could be as hard or harder than the creation of Common Lisp, but it is something to think about.

*When I talk about Lisp I mean Scheme, Scheme dialects, Common Lisp, ect, not just versions of Common Lisp, which is what some people seem to think it means.

Posted in Common Lisp, Scheme Community | 5 Comments »

Planet Scheme is Back

Posted by Peter on April 4, 2006

Planet Scheme is finally back, in a new home. Why can’t we just use Planet Lisp? Well Planet Lisp should really be called Planet Common Lisp, as they really only aggregate Common Lisp blogs. More importantly this blog is part of Planet Scheme, and not part of Planet Lisp, and I know you can’t live without it. One downside to Planet Scheme is that either my rss feed generator, or possibly the site software, has a tendency to cut my posts off in the middle. At first I thought this was a problem, but I have come to see that in some ways it is a benefit, as it cuts me off when I ramble on and on witho

Posted in Scheme Community | 4 Comments »

 
Follow

Get every new post delivered to your Inbox.