Skip to main content

Why I never got into Lisp

Like many programmers (I suspect) who hear enough Lisp afficionados talk about how great their language is, I've given Lisp a try. Twice. I didn't make much headway on either occasion.

For various reasons I was poking around python/lisp in google tonight and I came across this thread from a couple years ago. This crystalized it for me:

now compare
        if x > y or a == 0:
            a1 = m * x + b
        else:
            a2 = m / x - b

with
        (if (or (> x y ) (zerop a))
            (setq a1 (+ (* m x ) b )
            (setq a2 (- (/ m x ) b )).

In this case, Lisp requires about 33% more typing, almost all parentheses.

And, oh yeah, I forgot, aside from the parentheses, the pervasive prefix notation can be a drag.

Syntax does matter. Everyone who has run screaming from a steaming pile of Perl understands this. Lisp's syntax isn't the train wreck that Perl's is; at the very least it's consistent. I could get used to it if there were no alternatives.

But Lisp syntax was designed 50 years ago to make it easy to parse! We don't have to optimize for this anymore -- it's time to optimize for the programmer!

Today, Python and others have the features that made Lisp powerful without the syntactical baggage. Python has its own advantages, too, such as one of the best-designed standard libraries around. (Hence Paul Cannon's Lisp-to-python-bytecode compiler.)

Further reading: On the Relationship Between Python and Lisp.

Comments

Jonathan Ellis said…
Lisp people love to go on and on about macros, since it's pretty much the one thing that remains unique to them. (With the exception of other even-more-fringe languages like Dylan.)

I think that the rather profound lack of interest in macros in the rest of the industry constitutes the best reply. For 99.99% of applications, you don't need macros. (Peter Norvig, a well-known Lisp guy, explains why: http://www.norvig.com/python-lisp.html.)

For that 0.01%, I guess you're welcome to use Lisp. Just as you're best choice for a Linux device driver is probably C. No one language is best for everything... but Python seems to hit a sweet spot.
Anonymous said…
I think your post is missing some important points:

- LISP remains a more powerful language than Python, not only because of macros, but because of the fancy ways it lets you control evaluation (partial quoting, etc.).

- LISP syntax was not just "designed 50 years ago", there is something fundamental and minimalistic about it. In other words, it isn't "just syntax", it is also program structure, there is not conversion to an AST. This presents some advantages for low-level hacking.

- Some LISPs use dynamic binding (which is a different concept than dynamic typing), whereby the variables of the caller are available in the environment of the callee.


If only LISP had all the nice libraries that Python comes with, I personally would be using LISP. Also, understanding LISP can help you truly understand the nature of Python and computer languages in general, which is not true of Python IMO. Learning LISP is hard, simply because it is very rich and forces you to be explicit about everything (e.g. quoting), and because it blends the notion of language and libraries-- the language itself is just a thin core of the important most powerful concepts.
Anonymous said…
I use several languages all the time. Yesterday, I used OCaml, Java and Python. I haven't used much Common Lisp or Scheme lately, but I'm relatively fluent in both.

I've pretty much abandoned hope of finding a language that hits any particularly sweet spot. Each has its strengths and weaknesses. Each helps you see things from a slighly different viewpoint and often highlights the good and the bad in other languages.

Using Python you get a practical highly dynamic language with tremendous library support.

On the other hand, Common Lisp shows you can have an extremely powerful dynamic language and still be fast. Common Lisp, Scheme and the other more or less functional languages also pretty well highlight the silliness of statements in a language (as opposed to expressions). Looking at a Scheme implementation with a module and object system you notice that Python isn't all that different after all. The ML family shows you don't have to have prefix notation to have everything work as expressions and that static typing doesn't have to suck (but you still miss the dynamic features every now and then.)

As for macros, I find them to be useful. I don't use them a lot in everyday programming with CL and Scheme, but I do use them, most often of the with-foo-bar kind. Python has acquired and continues to acquire features that lessen the need for macros, but I think that it would be easier for all to just add the generic feature instead of lots of small specific ones. It would help keep the size of the core language in control.
Anonymous said…
Have you heard of M-expressions?
http://en.wikipedia.org/wiki/M-expression
They help somewhat, at least making Lisp look like C-style function calls instead of lists.
But still, your point remains quite valid. It's amazing how the verbosity of a language can have such a significant impact on its popularity. But since hackers are lazy (in a good way [see Hackers and Painters]), it's no surprise. Reminds me of COBOL - MULTIPLY A BY B GIVING C.
However, Dylan (http://en.wikipedia.org/wiki/Dylan_programming_language) sounds like a nice compromise - ALGOL-like syntax with macros.
Overall though, I see little advantage to macros over Ruby/Smalltalk's anonymous blocks.
In short, YAGN macros, and hackers like terse languages, like DWIM.
the paul said…
Devious of you to invoke my name and make me comment!

Maybe the best way I can explain why I like macros (and thus, lispy syntax) is Paul Graham's comment that goes something like "the shape of a program should reflect only the shape of problem it's trying to solve". Meaning, if you see patterns in your code, it's probably a place where you could use a macro to more directly match the shape of the code to the problem. Then when something needs to be changed, there's always one place to change it. Basic computer science stuff, but beautiful things happen for me when I take it to the next level.

No, I never _need_ macros, or functions, or anything else, but they can sure improve readability, maintainability, and coding time.

Anyway, I'm sure it doesn't fit everyone's coding style.
Anonymous said…
Commented on this post at my blog. I'm a firm believer and preacher in the belief - Every language has its place. Whatever tool fits the job use it.
Blindly supporting a language as 'the best' is silly and causes nothing but trouble.
Anonymous said…
"I think that the rather profound lack of interest in macros in the rest of the industry constitutes the best reply. For 99.99% of applications, you don't need macros."

Well, "the industry" ignored GC, bignums, closures, and a dozen other features that Lisp has, for *decades*. For a long time "the industry" standard was C; that does not mean it's a good idea.

Yes, you don't need macros for 99.99% of programs. In fact, you can write 100% of applications on a Turing machine. That doesn't mean there isn't something better available.

As for your original example: yes, when doing a bunch of arithmetic, s-exps are not the best syntax. A vanishingly small fraction of code I've written in my life consisted of line after line of arithmetic. And whenever I've had to do that in Lisp, I just whip out a reader macro that lets me bang out code that looks remarkably like your Python example.

That's another strength that Lisp has that I've yet to see another language match: if you don't like the syntax, write your own. Python is a neat language, but if its syntax isn't ideal for a particular application (like my current job), you can't adapt it to work better. And when you get beyond "a1 = m * x + b", it's really nice to have.
Anonymous said…
Strange, I find that I need to write macros for 100% of my programs. Having several years of professional experience working with Python, I now use Common Lisp everyday instead. As I remember it, always when I wanted to use Python in a project about 99.9% of the customers and 70% of my coworkers thought it was a very odd thing, and I ended up having to do it in C++ or Visual Basic instead.
That thought me I am usually right and 99.9% are usually wrong. Python? A scripting language? We can't hire anyone who know it!
Anonymous said…
Macros are hardly the only unique feature Lisp offers.

- There is still no object system as powerful as CLOS, nor is there any other object system that allows you to redefine its semantics in certain situations to help match your application better (see the Meta-Object Protocol)

- No other language besides Smalltalk comes close to Lisp in terms of interacive development - i.e. working with a running Lisp program at all times and redefining code, classes, etc. as you work with it, instead of just playing with a static piece of text that gets fed wholesale into an interpreter or compiler. This has led to the development of powerful IDE's like LispWorks, Allegro, or (to a lesser extent) SLIME. And the IDE's that ran on the Lisp Machines of old were even more stunning. Because you are always working with a live Lisp image, you can create and inspect objects on the fly, browse class hierarchies, etc., all without having to give up that dynamism.

- You downplay macros because you can't have them in Python. But they really are a huge win, despite what Mr. Norvig might say (by the way, Norvig's book Paradigms of AI Programming is a superb way of picking up Lisp). For more evidence, read or skim through: http://gigamonkeys.com/book/practical-an-mp3-database.html focusing particularly on the use of the macro define-binary-class, which is not part of CL and was defined specially by the author.

- Your assertion that Lisp's lack of syntax is simply a result of making life easier for the parser is, frankly, ridiculous. Were that the case, surely someone would have imposed a better syntax over Lisp in the last 50 years. And, in fact, people have tried. But Lispers like myself actually think of the syntax as a *plus*. When you use a Lisp-aware editor, you will see how much easier it is to move through trees of code instead of the clumsy by-line and by-character motion that's the best you can do in most languages. The simplicity of the syntax is what allows macros to exist and is a crucial part of Lisp's aesthetic appeal (that last phrase might sound ridiculous to people still fixated on parentheses, but everyone has that reaction initially until they start writing and working with Lisp code)

- It's fast. Fifty years of experience writing Lisp compilers has paid off. Most Lisps compile to native machine code (a few compile to portable bytecode instead). You have incredible control over the optimization of hotspots in your code. For example, you can turn on static typing for specific variables to save the time spent on typechecks.

- Maturity. Although Lisp's open-source library situation leaves a little to be desired (but not as much as outsiders would have you believe), the language, its common idioms, etc. have been around for decades and have survived the test of time. Research at academic institutions and in industry has refined Lisp over the years.

- Miscellaneous features, like "special" variables, the LOOP macro, the powerful FORMAT function, infinite-precision interger arithmetic, distinct list and vector types (Python does not understand the distinction, AFAIK)

Your suggestion that Lisp has wrongly been allowed to survive for 50 years is, frankly, pretty arrogant. You admit that you haven't yet grasped the language, yet you are willing to defy fifty years of experience and the praise of some of the brightest minds in computer science (Alan Kay, Gerald Sussman, Guy Steele, Edsger Dijkstra, David Moon, and on and on) and let everyone know that Lisp is really just a lot of hot air.

Well, thanks for the insight, Mr. Ellis. Can I kindly recommend that you at least learn the language (and if it's not too much to ask, that you also complete a small-sized project with it, so you can see how Lisp's features really pay off for programming-in-the-large) before gifting the Internet with your thoughts on it? In exchange, I promise not to make disparaging claims about Python on the Internet until I've done something worthwile with it.

Deal?
Anonymous said…
And just to clarify, Lisp's syntax had nothing to do with parsing. It was created as a mathemtical notation - a simple way of expressing algorithms. One of McCarthy's students decided to make a computer language out of it, against McCarthy's wishes.

The two wrote a syntax for Lisp that was meant to replace M-expressions, but surprise, surprise, no one was interested in it. Does it still sound like the syntax was a hack for parsing?
Anonymous said…
I use macros all the time.

Instead of:
(define (on-today) (void))
(define (on-calculate) (void))

(define (set-on-today fn)
(set! on-today fn))
(define (set-on-calculate fn)
(set! on-calculate fn))

Which is ugly and verbose, I can use a macro.

(This is Scheme, of course)

Popular posts from this blog

Python at Mozy.com

At my day job, I write code for a company called Berkeley Data Systems. (They found me through this blog, actually. It's been a good place to work.) Our first product is free online backup at mozy.com . Our second beta release was yesterday; the obvious problems have been fixed, so I feel reasonably good about blogging about it. Our back end, which is the most algorithmically complex part -- as opposed to fighting-Microsoft-APIs complex, as we have to in our desktop client -- is 90% in python with one C extension for speed. We (well, they, since I wasn't at the company at that point) initially chose Python for speed of development, and it's definitely fulfilled that expectation. (It's also lived up to its reputation for readability, in that the Python code has had 3 different developers -- in serial -- with very quick ramp-ups in each case. Python's succinctness and and one-obvious-way-to-do-it philosophy played a big part in this.) If you try it out, pleas...

A week of Windows Subsystem for Linux

I first experimented with WSL2 as a daily development environment two years ago. Things were still pretty rough around the edges, especially with JetBrains' IDEs, and I ended up buying a dedicated Linux workstation so I wouldn't have to deal with the pain.  Unfortunately, the Linux box developed a heat management problem, and simultaneously I found myself needing a beefier GPU than it had for working on multi-vector encoding , so I decided to give WSL2 another try. Here's some of the highlights and lowlights. TLDR, it's working well enough that I'm probably going to continue using it as my primary development machine going forward. The Good NVIDIA CUDA drivers just work. I was blown away that I ran conda install cuda -c nvidia and it worked the first try. No farting around with Linux kernel header versions or arcane errors from nvidia-smi. It just worked, including with PyTorch. JetBrains products work a lot better now in remote development mod...

A review of 6 Python IDEs

(March 2006: you may also be interested the updated review I did for PyCon -- http://spyced.blogspot.com/2006/02/pycon-python-ide-review.html .) For September's meeting, the Utah Python User Group hosted an IDE shootout. 5 presenters reviewed 6 IDEs: PyDev 0.9.8.1 Eric3 3.7.1 Boa Constructor 0.4.4 BlackAdder 1.1 Komodo 3.1 Wing IDE 2.0.3 (The windows version was tested for all but Eric3, which was tested on Linux. Eric3 is based on Qt, which basically means you can't run it on Windows unless you've shelled out $$$ for a commerical Qt license, since there is no GPL version of Qt for Windows. Yes, there's Qt Free , but that's not exactly production-ready software.) Perhaps the most notable IDEs not included are SPE and DrPython. Alas, nobody had time to review these, but if you're looking for a free IDE perhaps you should include these in your search, because PyDev was the only one of the 3 free ones that we'd consider using. And if you aren...