Posted: Mar 13, 2012 9:38 am
by VazScep
stalidon wrote:Yeah, Lisp has a long-lasting heritage... and since I started programming in the 80s Lisp was on my 'to check' list...

Would Scheme or Haskell give me a taste of Lisp's paradigm? That is, are any of them an 'upgrade' on common Lisp, or different paradigms altogether?
I wouldn't learn Haskell if you want to learn Lisp. Some people would say that Haskell is an upgraded Lisp, but I don't much care for the view. The Lisp attitude with regards to typing is completely polar opposite to Haskell, and there are a lot of ideas that Haskell threw out of the Lisp view of the world, including the sole thing that makes Lisp unique among all languages: code is data.

Don't worry about finding an "upgrade" to Common Lisp. Common Lisp was built on a philosophy beautifully explained here. It's designed to do the "right thing" all over the place, making it an extremely powerful language at the expense of making it extremely difficult to write a conforming implementation. One reason there are no upgrades to Common Lisp is because they are a nightmare to implement efficiently (as the essay explains, this is also the reason why we haven't really upgraded from UNIX).

That is why there are a great many interesting ideas implemented in Common Lisp that I have never seen implemented anywhere else. I am happy to be corrected, but I have never used any other language whose debugger compares: when you hit a runtime exception in Common Lisp, you are given a stack-trace and you enter a debug loop. Here, you can navigate up and down the stack-frame, inspect the arguments passed to all of the functions in the stack frame, and ask Lisp to try rerunning any of those functions but with new arguments computed from arbitrary Lisp code. You can generally write arbitrary Lisp code in the debug loop. So you can happily rewrite the source code of an offending function, recompile that function from the debug loop (in Lisp, you have access to the compiler at runtime via the ordinary Lisp function "compile") or rebind offending global variables, and then continue execution or retry execution from any part of the stack frame as if nothing had ever gone wrong. There are great stories of shipped Lisp systems, which, when they crashed, the developer would simply ssh into the machine, fix the bug at the stack-trace, and then let the system carry on business-as-usual as if there had been no downtime. (Admittedly, Smalltalk does this sort of thing even better, but that's why Smalltalk is sometimes called a Lisp).

When I first started learning Python, I remember doing some extensive testing at the toplevel, creating a whole bunch of instances of my various classes and putting them together. I then fixed a bug in a class definition, by redefining one of its methods, and then reloaded the code at the toplevel. I was surprised to find that none of the instances I had previously created had the new method.

Python programmers pointed out to me that this was to be expected, that only new instances would respect the class redefinition. This attitude is itself to be expected from a bunch of people who have such low expectations from their technology that they think Python is an achievement, and not just a poor man's Smalltalk. It is worse-is-better. The right thing is what Common Lisp does: it tells every instance to bring itself up to date with the new class definition, a procedure that is compounded in its righteousness by the fact that the behaviour can be customised by specialising "reinitialize-instance" with your own metaobjects. Like I say, Common Lisp is a bastard in its complexity, but a delight for its users.

If you want a Lisp, Common Lisp is the most Lispy Lisp there is.

For a Win32 implementation, use CLISP, because it's free. You can also use Corman Lisp which has a 30-day trial.

Generally, you're better off on Linux. In fact, the only reason I started using Linux and Emacs in the first place was because I was getting into Lisp.

This is just if you're curious about the Lisp heritage and want to see some cool ideas. Alternatively, if you want to use a Lisp in the 21st century, check out Clojure. For a relatively new language, Clojure has totally taken off, competing head-on with Scala to be the language for the Java virtual machine. It's also a pretty damn Lispy Lisp, keeping many of the ideas that makes Common Lisp great, adding in some ideas from ML-style functional programming (such as ML style references, software transactional memory, agent-based concurrency, and an emphasis on immutability) and throwing out all the crud that made Common Lisp stupid (such as separate namespaces for variables and functions).