I've heard all of these arguments in support of Lisp for many years, but I'm still not convinced. Indisputably, Lisp is remarkable and holds a special place in the pantheon of programming languages. Every argument in it's favor makes sense, a lot of sense. Reading these arguments in favor of Lisp is not like reading a blog touting the benefits of Javascript where even the positive points don't really sound so positive. The arguments made for Lisp are persuasive.
Lisp is different. It's really quite unique; it has an elegant simplicity underlying its implementation and a deep connection to the foundations of computation. Think of this, Gregor Kiczales's book Art of the Metaobject Protocol was published 23 years ago! I learned to program in Lisp 40 years ago. What other languages did I use back in those days? Assembly language (IBM 360, CDC 6600, IBM 1130, etc), PL/1, Fortran, APL, COBOL. Nobody, argues today that we should be trying out PL/1 or we should give COBOL a try. (Are there any projects on Github using these languages from our hazy, distant past?) Lisp's beauty and power have kept it alive and vital all these years. But, there's something wrong with this story.
If Lisp is really so great, why hasn't it triumphed? I use Lisp all the time: my editor needs it during periodic tune ups. However, I can't think of when I've reached for it first when I've had a choice. Python is just easier to get things done in. If my programs don't run fast enough I don't think of Lisp, I think of C or C++. Haskell is where it's at as far as programming language research goes, not Lisp.
The important observation is that it's not just me. Lisp has had time to prove itself. It made it to the finals, and it deserves the lifetime achievement award. We can honor it's beauty, it's longevity, it's power, and even it's fantastic reincarnations (Clojure), but this isn't enough. If Lisp really was the language that we should be programming in, it would have demonstrated it by now.
As I often say, LISP is the language of the future, and it's been the language of the future since before I was born (in 1965!). It will always be the language of the future. If it hasn't become the dominant language in 50 years of computing, it probably won't happen. On the other hand, it hasn't died in 50 years of computing either. The only other language that has shown that kind of longevity is C, which came into being less than a decade after LISP.
Frankly, I think a lot of the problem is social. LISP proponents have a historical condescension that really doesn't sit well with all the programmers that they think are idiots for not using LISP. Less stick and more carrot would go a long way. Consider the thread elsewhere in this discussion that whines about how Clojure even got mentioned! Clojure is exactly the sort of carrot that will bring current programmers into the functional paradigm. Bashing it because it's not pure enough is lunacy if you ever want your language of choice to be dominant, and not merely feel smug and superior to the lazy corporate sods who use crap languages. I see these attacks and remember the attacks on Scheme long ago - same issues.
I firmly believe large social things happen for a reason other than "people are stupid". If LISP holds only a tiny corner of the programming world while some genuinely dreadful languages (PHP!) rule the roost, there's probably more to the story. It would do the LISP community some good to meditate on that for a while.
I think this is a recent phenomena, which probably developed after the late '80s AI Winter et. al. crash. When Lisp was ascendant in the early '80s, the attitude, at least in the MIT community, was that everyone could and if they so desired should learn Lisp.
Bernie Greenberg, among many other things the author of Multics Emacs, which used Maclisp as one of its implementation languages and of course as its extension language, was immensely proud about MIT secretaries using it to turn keyboard macros into real extensions.
Although, he was a major evangelist at the time, author of a great intro I've been trying to find a copy of, the guy who said "Cons is an object which cares. It cares about its car and cdr", etc. etc. But he was fully supported by everyone I knew in the MIT Lisp community.
And I think Scheme escaped some of this, or at least it didn't suffer like CL did since it retained its place as a teaching language for quite some time, only falling in this century (e.g. MIT panicked after the dot com crash resulted in EECS enrollment dropping more than by half, Berkeley recently retired its SICP class when professor Brian Harvey retired, etc.) ADDED: and unless things have changed very recently, has retained its place in computer language development. Heck, while not the same thing, Javascript is basically a Scheme with a prototype-based object system and C style syntax.
Clojure as far as I can tell has escaped this, then again it's being quite successful currently and per my guess above that would help a lot.
As for the "people are stupid" thesis, our host has interesting commentary in that direction with his Blub language hypothesis: http://www.paulgraham.com/avg.html
BTW, as I understand it, FORTRAN, the first computer language (Lisp is the 2nd oldest survivor) still is very big in number crunching.
"Recent" in this case is still before many current programmers were even born. 25 years ago isn't really recent anymore.
As for FORTRAN, there are a couple of reasons. First, the ability to skip a pointer dereference on large tables for performance, and second, the existence of fine and ancient libraries for well-known problem spaces. I used to work with some old Cray guys, and they would rant about how FORTRAN was the best language ever on purely performance grounds.
Indeed for "recent", but then again we're discussing a language which first appeared in 1958, 3 decades before the cause I posit for the mainline/CL community becoming ... not so nice. Note that I don't really know, I left it for Scheme by the middle of the '80s.
Is no one writing large bodies of new FORTRAN code? Or is it mostly in COBOL style maintenance mode, and e.g. called a lot by Python, which I gather is getting a lot of attention in the scientific community (I started with IBM 1130 punched card FORTRAN "IV" in 1977 in a academic year long class, but stopped after that, it wasn't an answer for the sorts of problems I was interested in, C and Lisp are).
Fortran is very heavily used for development in numerical weather prediction. For example, the WRF model (http://www.mmm.ucar.edu/wrf/users) includes hundreds of thousands of lines of code and has been under continuous development since the late 1990's.
And Fortran has evolved significantly in the last two decades, absorbing many features (and lessons learned) from other languages. Structures, modules, encapsulation, argument checking, pointers, allocatable arrays, classes, inheritance, function overloading, pure functions.... Wikipedia has a decent summary (http://en.wikipedia.org/wiki/Fortran).
I dunno. I haven't looked at what's going on with FORTRAN in a meaningful way in years. It might largely fall on how algorithms designed to exploit long-obsolete vector processors have been adapted to work on modern, highly parallelized supercomputer networks, with powerful but conventional individual nodes separated by really slow networks.
I think whether they knew it or not, old Lispers couldn't communicate with the world without friction. The paradigm shift was probably too large, even nowadays a lot of people will frown even though gc, closures, map/filter and other idiom have bubbled up. I felt the same the first time I saw ML.
Hackers by their very nature seek mastery over challenging concepts. I think haskell and lisp are similar in the sense that they have long roads to mastery. The average hacker in these languages spends many exhilirating years scaling the tower of knowledge and this journey does a great job of keeping the hacker occupied and mystified. In simpler languages like C / Javascript there is very little in the language with which to immerse yourself. The only recourse for a stirring experience is to go ahead and build something immersive.
Haskell and Lisp are great languages for thinking deep thoughts. Expecting them to dominate the computing landscape is similar to expecting an abstract algebra book for topping the New York times best sellers list.
Read up on e.g. the history of LISP at JPL: it's termination with extreme prejudice was basically done on a political whim.
This is not to say the Scheme and Common Lisp communities didn't get massively and almost/perhaps terminally wedged in the following periods, but that's another story. Many of us old time Lispers say look at Clojure for the likely successful future of Lisp.
Finally a quote by Kent Pitman I like: "Please don't assume Lisp is only useful for Animation and Graphics, AI, Bioinformatics, B2B and E-Commerce, Data Mining, EDA/Semiconductor applications, Expert Systems, Finance, Intelligent Agents, Knowledge Management, Mechanical CAD, Modeling and Simulation, Natural Language, Optimization, Research, Risk Analysis, Scheduling, Telecom, and Web Authoring just because these are the only things they happened to list."
You're right about fashion and politics. Social issues, those are the problems a lisp really faces.
Yep, it's that JPL account I was too lazy to look up. Just like the AI Winter, a convenient scapegoat.
To acquisitions dumping LISP you could also add our host's Viaweb, right?
ZIL is derived from MDL: https://en.wikipedia.org/wiki/MDL_(programming_language) which has a critical place in the subsequent development of things like Scheme. And, yeah, Zork was written in it. I had a lot of fun with Adventure on a Version 6 UNIX(TM) back in 1978, so Zork on MIT-DM in 1980 or thereabouts was simply amazing.
Finishing, by fitting into the wildly successful and very useful Java ecosystem, Clojure avoids one set of political issues (heck, Java made the world safe for GC language in general). And with a number of success stories, and to my very limited knowledge no major horror stories yet, another.
But when we're talking about fashion and politics that sort of bourgeois truth doesn't matter. But we'll see.
I'm replying to my own comment because the other commenters have made such good points and I'm responding to several at once.
I wish that in my rather long career that I had a chance to work on a big project using Lisp. How else can one really make judgements about the suitability of a programming language. Simple programs and personal projects don't give one a feeling for the value of many important and perhaps subtle language features that have significance at a scale where we all all strive to improve our tools. So I can't speak with the authority of the other commenters, and I relish the comments of those that have had industrial level experience with Lisp (see hga’s comments).
However, I have read books on Lisp, dozens of them. I've worked in the group that implemented a commercial Lisp at Texas Instruments. I've owned a copy of the InterLisp reference manual. I've programmed in Lisp before Common Lisp existed. I used Lisp in a classes taught by Patrick Winston and used Lisp and lambda calculus to understand CLU's semantics while working on my undergrad thesis with Barbra Liskov. I took the class before SICP was a book; I’ve still got the mimeographed notes. I not a Lisp expert, but I'm not even close to the troll end of the scale either. Of course I'm familiar with Blub and Phil Grahamm’s other essays, everyone could benefit from reading these. He explains one of Lisp’s great benefits: it makes you a better programmer. I know it has done this for me; I was wrong to suggest that Lisp hasn’t triumphed (see dman’s comments).
Once upon a time I tried to introduce Lisp as an important part of our system architecture in my company, but the other engineers objected ("too many parentheses"!!). To avoid outright mutiny I developed an alternative design that didn't need a Lisp interpreter. Perhaps I should have not given in. (see mrrottenkolber’s comments).
Not being an expert on Lisp, I’ve tried to figure out how much energy to put into further developing my skills there. Should I direct companies that I run or consult for to use it? Or should I tell them to use something else? This is the dilemma that I face, and this is why these discussions interest me. As jules notes, many of Lisp’s contributions to programming languages have now made their way into the most popular languages today.
"Too many parentheses" is a cop out for "This language is too far out of my comfort zone." And I think that is why Lisp is not as successful as other languages.
I also think the almost mythical status of Lisp is also a hindrance. Lisp couldn't possibly live up all the hype. This leads to a backlash of common complaints ("not enough libraries", "smug lisp weenies", "bad culture", "no ide", "prefix notation is unreadable") when it does not live up to the hype or worse the user fails to grok lisp. The mythical status also leads to a higher percentage of trolls.
Back in the day, most programming was from scratch or at most trading bits of code. Lisp was great in this environment. Coding from scratch was quicker than other languages and due to its dynamic nature morphing someone else's lisp code was easy. Today most programming is patching together libraries or tools. Scripting languages are ideal for this. No one "steals" code any more, they "steal" whole libraries.
Lisp isn't even all that unique any more. Garbage collection, closures, REPL & macros are all available in other languages these days. Scala for instance has all these features.
Homoiconic isn't actually a very meaningful term. In Scala code is also represented as a data structure (AST), and macros produce ASTs. Heck C code is represented as a data structure: the string (although of course C does not have macros like Lisp & Scala).
In my post I said: "a fully homoiconic programming language where code is represented as a simple data structure at the heart of the language." By which I mean: a core built-in data type that is well supported and easy to use.
I wouldn't call an AST a simple data structure at the heart of any of the languages you mentioned. The powerful thing about LISP is that when you manipulate data the easiest tool to reach for is lists, and when you manipulate code you use lists.
An AST is just objects. Just like Lisp was designed to manipulate lists, Scala is designed to manipulate objects. The difference is that an AST has more structure, which is a good thing. The least structured are just plain strings, then come s-expressions, then ASTs. Lisp is only halfway there to a modern macro system.
I beg to differ. I won't even look at a language who doesn't have a macro system like CL does. Which only really works out well if its homoiconic.
(For serious use that is, certain feature can of course be interesting regardless of others, e.g. I find erlang's implementation and concurrency mechanisms very interesting.)
I think it proved its superiority many times. Its just that certain people couldn't admit it to themselves. Other langs are just a great way to ignore cold hard engineering facts and give grunt-work developers a feeling of perfection.
Of course you don't need a lisp to build CRUD apps. Companies don't want to depend on highly trained engineers either. I don't care for being cheap though. I'd rather know 10% of lisp than 100% of yet another dead-end language.
Yes! Lisp is the superior language! The only reason it doesn't dominate all others is that most programmers are too stupid to see how wonderful Lisp is!
Ahem.
You'd be somewhat more persuasive if you dropped the arrogance and stopped assuming that those who disagree with you are self-deceived fools.
Except this: "Yes! Lisp is the superior language! The only reason it doesn't dominate all others is that most programmers are too stupid to see how wonderful Lisp is!" ...is exactly right. Not even hyperbole. Exactly right.
I was a fool until I understood LISP. The arrogance is warranted. One is a fool at least until getting LISP, this is not an assumption but a statement of fact.
(I actually got mad once I got LISP because I understood the awful waste that exists in the form of non-LISP languages.)
Why then do you criticize the tone and not the argument.
Again: Non-lispers are cheaper that lispers, thus it is not in the industries interest to have enlightened engineers, because for 90% of the business you don't require the enlighentment.
Why do I criticize the tone and not the argument? Because there isn't much argument there. (Note well: I did not say that there isn't much in the argument to criticize. You haven't given much of an argument - just a smug assumption of superiority, and that's all. I criticize the tone because that's all that's there.)
If you want to persuade people, give them a reason to believe what you say. "Believe me because I'm smart and you're stupid" is not a persuasive argument.
If you don't want to persuade people, if you just want to wallow in your superiority in your self-imposed ghetto, that's your business. But if so, would you mind not wasting our time with your statements of superiority?
And: Non-lispers are cheaper than lispers? Perhaps the average lisper is better paid than the average non-lisper. Did you control for years of experience and such? And if for 90% of the business you don't need people who know lisp, then maybe lisp isn't the best tool for the job except in 10% of the cases. Maybe you should stop thinking it's best for everybody?
Look, I don't want to persuade anybody. If you are interested in why I am so smug just give Lisp a try, if that same smugness puts you off, no problem, nobody minds. I am smug because people rather dare to criticize me that way.
Not cheaper in terms of salary. Cheaper in time needed to train. You can use e.g. Python or Ruby without knowing how its implemented (if you knew you wouldn't use it). A Lisp programmer automatically needs to be a full stack developer, or at least conscious about the stack, because he is operating a compiler framework. It has lots to do with circular definition and choosing the right tools bottom up. For instance, most of CL can be and is implemented using a core part of the language. What that core is can differ from implementation to implementation. So the barrier between user and creator is very small in Lisp, thats what makes it so powerful and demands its users to be well trained in many aspects of software systems.
I think the more knowledge you have of your environment, the better you can solve a problem in it. So I think most programming problems can be better solved in a lisp than in any other language (so far).
If I knew how Python or Ruby was implemented, I wouldn't use it? BS. I'd use it if, weaknesses and all, it was good enough to be useful for what I was trying to do. Anything else is posturing.
I'm curious if you, and other lispers, do acknowledge the possibility of there being languages whose users are rightfully even more smug than them? You think that you are enlightened and have seen lisp being superior. Yet perhaps you have only opened the first door and there is a whole world of even more powerful and algebraic programming abstractions you aren't aware of?
An interesting next step to Turning machines I read about recently was Kolmogorov-Uspensky machines. They allow pointers and are nearer to real machines we use. Whilst they still recognising the same languages in polynomial time as Turing machines, for some things they can compute and order of complexity class faster. Turing machines often end up traversing up and down the tape, linearising binary tree lookups for instance, whereas KU can do binary tree lookups in O(log(n)). Both machines do the lookups in P, but KU's particular P can be provably lower.
Have to say by now I am tired of clicking on a Lisp titled article and having to read about Clojure. Please stop hyping Clojure. It's not LISP and its not Lisp either. We have a Lisp, it's called Common Lisp, its perfectly fine, far superior to Clojure and will prevail Clojure by decades.
To underline how awfully skiddish Clojure is from a lispers perspective, the first thing he mentions is the "thrush macro":
http://clojuredocs.org/clojure_core/clojure.core/-%3E
Which is needlessy to say a typical example of the skiddish culture of Clojure.
The brain train goes like this: "Oh we have grown this ugly zombie breed between a ruby and a java, how to we make it look intentional? Oh that's easy just put on a little of this completely pointless macro cream to make it look hip!"
Worst: The article isn't even about Clojure. Please in the future label Clojure as what it is (an experiment in STM), and do not forget to mention that we have a great standardized language with great implementations which make the whole industry look bad. And we have that because engineers worked on it for decades.
Edit: Thank you kind power-user for going through the whole thread and downvoting every comment I made, that's the kind of cargo-cult marketing I was talking about. I think downvoting shouldn't exist, makes it unpleasant to comment on topics where you don't share the mafias opinion. Yay HN!
Nothing against Common Lisp but CL is not the lisp and it never will be. CL is a lisp same as Clojure - http://www.islisp.info/faq.html. Also you seem to have no problems critiquing a language which you obviously have no significant experience with - "Clojure is an experiment in STM". Guffaw.
As a historical example, mainline LISP prior to CL was dynamically scoped, something corrected in Scheme and adopted by CL a decade later, which, from my Maclisp and Lisp Machine Lisp background at the time was perhaps its biggest breaking change (very possibly not from the viewpoint of an Interlisp person).
Everything in Clojure had to be implemented new. There is zero compatibility and zero code sharing to/with Common Lisp, Emacs Lisp, Autolisp, ISLisp, Standard Lisp, Maclisp, Lisp Machine Lisp, ...
One of the reasons that Clojure has so many libraries is that most things didn't have to be implemented from scratch.
Building Clojure on the JVM was a genius move by Rich Hickey - it meant that an advanced runtime platform (the JVM) and a huge ready-to-use library ecosystem was already there from day 1.
Backwards compatibility with Common Lisp was never a goal. The JVM ecosystem is bigger by far (and IMHO more valuable as a target).
What about Scheme? Sure, it was bootstrapped in Maclisp, but not too long after had pretty much "zero compatibility and zero code sharing" with mainline LISPs. But is it not a LISP?
1) the Lisps: they carry the name and share basics: Lisp 1.5 ... Common Lisp, ...
2) the derived dialects with some compatibility: Scheme, Interlisp, ...
3) the derived^2 dialects: Logo, MDL, Dylan, Racket, Clojure, ...
4) the derived^3 dialects: ML, ...
The Lisps is category one were and are able to share code. Emacs Lisp implements some of Common Lisp. Something complex like the LOOP macro was once a single source file for Maclisp, Lisp Machine Lisp and Common Lisp.
Clojure shares no source code with any other Lisp. It renames basic vocabulary ('atom') and lacks some older concepts. It's basically a new language.
OP here. I didn't realize that Clojure was a trigger word! I just included that bit at the beginning to give a little context on how I got into this topic, not to hype anything.
Clojure is more like scheme in that it only has a one scope environment. Common Lisp (and Lisp) are defined by having 2 scope in the environment. One scope for the functions and one scope for variables, if I remember correctly. An easy way to learn your way around lisp is to read and work through Graham's essay "Roots of Lisp": http://paulgraham.com/rootsoflisp.html
Well, as I score it, it's not a LISP, as in LISt Processing, since lists are no longer the principle collection type, and others are first class syntactically. Not to mention the use of vectors (denoted with square braces []) for special form syntax like in defn and let.
By "lists", you mean "linked lists as implemented with pairs"? What's the practical difference between lists and the seq abstraction (immutability aside)? It's true that Clojure provides a lot of data types, but none that would be unfamiliar to a CL programmer. And you can handle all of them more or less like lists, and as a bonus you can use the same set of functions to do so.
I would think that the immutability of these data structures would be a bigger difference, both conceptually and in the difficulty of porting CL code into Clojure.
Yes, as implemented with pairs, syntactically with parens.
None, except vectors and maps (and sets and regexs and ...) being syntactically first class, and being used heavily, not just in special form syntax but in real use. For a whole lot of programming, maps are where it's at for your data structures.
True, these shouldn't be unfamiliar to a CL programmer (although the pervasive use of maps might well be, don't remember how much association lists and properly lists were used).
As someone who adopted the mostly functional Scheme style I don't find the enforced immutability a bigger difference, but I could well see that being true for CL programmers. And for many/some? the bias against OO vs. CL's CLOS, which many claim is the very best OO system ever (as far as I know the only popular one with a MOP).
Like I said its an experiment. CL is a great piece of work forged by decades of engineering _consensus_. Feel free to take a look at ABCL if you want to know where the man hours of clojure should have went into.
Its just like ruby, a trend that a lot of effort is wasted on, because the fundamentals are plain wrong.
CL: Extensible, industry proven language with many implementations on many platforms. Big standards body which still only defines what is proven to be good by the test of time.
Clojure: An opinionated experiment with a single implementation that might just as well have been a library for CL (we do have STM libraries though, so there isn't really a point).
> CL: Extensible, industry proven language with many implementations on many platforms. Big standards body which still only defines what is proven to be good by the test of time.
This was once true, but CL's standards body last made a significant revision twenty years ago, and no longer exists. It petered into inactivity by the late '90s, formally lost its voting privileges due to lack of quorum by the early 2000s, and was dissolved in 2004 (http://mailman.rose-hulman.edu/pipermail/ncits/2004-August/0...).
Nowadays the consensus process is more community driven, more of a messy "modern-style" language evolution, and doesn't involve a formal standards body or any kind of centralized process. Implementations add proprietary extensions to experiment, and then compatibility libraries layer over those extensions, slowly becoming de-facto standards. For example multithreading can't be implemented in standard CL, and various CLs instead expose their own private threading APIs. Bordeaux-threads then arises as a compatibility layer and attempt at achieving consensus around a portable threading API.
Perhaps that isn't a problem, but it simply isn't the case that CL has a big standards body that defines what has been proven to be good: it has no standard body, which as a result defines nothing post-1994; the base language is frozen in time.
It really isn't a problem. AFAIK there isn't a run-time performance to using cross-implementation libraries. If you're building an application you probably don't even need to worry about supporting multiple implementations and can write to the available extensions directly. Fortunately the spec left us with a highly-extensible "programmable programming language." Libraries fill the gaps between implementations which push the gap as technology changes. The core is just the bedrock to build upon.
> This was once true, but CL's standards body last made a significant revision twenty years ago, and no longer exists.
It is STILL true that we have a great standard which only includes the "definitely right" things. And if you ask me, its just so good that we haven't needed a revision in 20 years.
And if you ask me, its just so good that we haven't needed a revision in 20 years.
What about threading and/or concurrency? CLTL doesn't mention it, yet it is something which is now considered a requirement for real, general purpose programming languages.
> its just so good that we haven't needed a revision in 20 years
This is part of why I no longer use Common Lisp (after using it professionally for about 10 years). There are clear bugs in the spec, but it will never change. If your language is not progressing, it is dead.
Nonsense. The standards process is a beast, so no one is going to kick it off for anything other than a good solid rethink. As others have noted, the language and spec are done, aka pretty much ideal. Go write some code, people.
ps. Love elsewhere a mention of "modern-style" language development. Sounds like "make it up as we go", what Lisp was doing in the sixties.
That's right: The spec will never be revised, not because it already defines the ideal programming language (is that really your argument?), but because the effort and expense is so great.
Maybe somewhere in between. The imperfections are so small that even a modest effort would never get undertaken. Something folks need to realize is that Lisp truly is a metalanguage: I think both Graham and Norvig knocked off quick and dirty OOP hacks when that (decent) fad came along. So it is hard to imagine what innovation might come along that would force us to get the Lisp hood up.
That library couldn't enforce Clojure's functional nature.
CL (Common Lisp) is "multiparadigm", and shows warts going all the way back to the original mainline LISP. I should note that I'm someone who prefers Scheme to mainline LISP, modulo library availability ... which is one place Clojure it really winning, CL is an abject disaster, and Scheme is very very late to the game (still a work in progress last time I checked, R7RS-small being ratified less than 3 months ago).
I also see value in making vectors, maps etc. first class syntactically (although I would have been happier keeping vectors out of special form and function syntax), the collection and sequence unifications, etc. etc.
To finish, Clojure was first released 6 years ago, I'd say it's getting past the experiment stage. E.g. I don't know how you count implementations, but the ones that run on top of the CLR and JavaScript mean something, especially the latter, and what I gather it's bringing to the party.
> And what about using persistent data structures by default
You can do that in CL if you like to.
> and having JavaScript as a compilation target?
See ParenScript.
> I also haven't heard much about how easy CL's host language inter-op is to work with...
CL doesn't have a host language. And look at ABCL please.
> Another big thing of course is that the community is much more vibrant and welcoming than Common Lisp's.
The community is more skiddish and therefore newbie friendly. CL's community may feel arrogant at first, but with time you will notice it was justified because you were wrong and ignorant about it.
> > And what about using persistent data structures by default
> You can do that in CL if you like to.
When you do this by default you do get a completely different ecosystem of libraries though, which is one of Clojure's key advantages over CL.
> CL doesn't have a host language.
Another one of Clojure's key features is that it's designed to be easy to implement on a host language.
That choice has some disadvantages such as forgoing the elegant condition system of CL in favor of plain old exceptions, but it also enables the practical use of Clojure and it's persistent data structures on a varied collection of host languages.
> CL's community may feel arrogant at first, but with time you will notice it was justified
We all know the Smug Lisp Weeny stereotype. I had the pleasure of talking with the original smug lisp weeny (smuglispweeny.blogspot.com) a couple of years ago about his OpenCells library which I still love as one of the most elegant solutions in computing.
OpenCells never went anywhere serious though but the Clojure ecosystem is starting to develop it's own version of the concept which runs on the browser right away and is already driving demo iOS and Android apps.
So yes, Clojure might not have the history of CL behind it and has less of a history of drawing bright minds into an ivory tower which contains infinite beauty but which rarely, if ever, makes down to earth.
You could say that makes it a toy, but if I had to place a bet on which language will have the biggest impact from now on then I'm pretty sure which language I would put my money on.
> When you do this by default you do get a completely different ecosystem of libraries though, which is one of Clojure's key advantages over CL.
This isn't even an argument. "Because its new."
> Another one of Clojure's key features is that it's designed to be easy to implement on a host language.
You just made that up. Clojure was designed to be able to run on the JVM. When implementing Clojure from scratch you will have to emulate the JVM. So the guys who will maybe (I don't think anybody will remeber Clojure in 10 years) do that in ten years will curse rich hickey.
I am not comment on the rest, because it has no content.
I think you're mistaking the parent poster's argument. Immutability is at its most useful when it's the norm, rather than the exception. For this to work, the core language needs to very strongly encourage immutability, to the point where in-place mutability is considered something only useful for low-level performance tweaks.
It's not that Clojure is new - there are plenty of older languages that have a strong core of immutability. The point is that it needs to be at the core of the language in order to be pervasive.
> You just made that up. Clojure was designed to be able to run on the JVM.
No he didn't. The Clojure rationale page talks about separating languages from platforms, and this subject has come up often in talks and on the mailing list. Clojure has already been ported to Javascript, and there are various projects to implement Clojure in Python, Ruby, C and Lua - that I know of.
There's also a lot of current work going on in abstracting out the Clojure analyser and compiler, both to bootstrap the language, and to make it easier to derive ports.
> I think you're mistaking the parent poster's argument. Immutability is at its most useful when it's the norm, rather than the exception. For this to work, the core language needs to very strongly encourage immutability, to the point where in-place mutability is considered something only useful for low-level performance tweaks.
I don't think so. What you are saying is you can only program in way X if your language forces you to, which is obviously wrong? I think people just are not used to using a language that doesn't force you to do anything at all (e.g. lisp).
You can only program in way X if your language _allows_ you to. What language allows you to program in any way and even lets you easily modifiy the language to do whatever you want? Lisp.
> The Clojure rationale page talks about separating languages from platforms, and this subject has come up often in talks and on the mailing list.
Then they made that up. ClojureScript is not the same as Clojure. They did a pretty horrible job at seperating their language from their platform. I know because I get Java stack traces all day. I also have to use inferior language primitives dues to Clojure's Java-centrism every day.
> I don't think so. What you are saying is you can only program in way X if your language forces you to, which is obviously wrong?
If you have a library that expects mutable data structures, that's going to be incompatible with a library that uses immutable data structures. The type signatures of the functions are going to be fundamentally different.
It's certainly possible to have a language without a consistent set of core data structures, but I'd argue that's considerably less useful. Enforcing a particular paradigm means you can interface between libraries without worrying about compatibility of data structures.
> Then they made that up. ClojureScript is not the same as Clojure. They did a pretty horrible job at seperating their language from their platform.
That's not quite what I meant. A particular implementation of Clojure is typically tied closely to the platform its hosted on. That's why Clojure and ClojureScript have marked differences, especially around concurrency.
What Clojure lacks, and deliberately so, is a platform of its own. There isn't an equivalent of the JVM in Clojure; there's no intermediate layer that sits between Clojure and the JVM, or ClojureScript and Javascript. The idea is that the language should adapt to its host, instead of trying to shoehorn everything through a universal interface that can't cope with every situation.
There's a pretty good argument that taking away features is what makes programming paradigms effective. You create restrictions (invariants, if you like) that enable the paradigm. Consider:
- Structured programming takes away GOTO
- OOP takes away manual function pointer tables
- FP takes away unrestricted mutation
- Logic programming takes away explicit specification of execution order
- etc.
None of this is about "forcing" you to do anything. It just appears that humans aren't very good at coding with unrestricted power over their machines, and it helps to simplify paradigms in a way that enables them to be effective at reading and writing higher level code.
If this wasn't the case we'd all still be programming in assembly.
Better stacktraces would be better, sure, but there are good arguments on both sides whether it's better to separate the language from the platform or not.
I prefer a thin, readable compiler and core library over such abstractions. I don't mind the stacktraces, but I could see how some people might.
The fact that clojure is host-centric makes clojure and clojurescript compelling to java or javascript programmers at the expense of some aesthetics, and it also has performance implications.
This is somewhat irrational critique, clojure was an opportunity to start fresh and graft a concurrency-focused lisp onto a pervasive runtime, not to reimplement ABCL. It fills a need.
I was always somewhat halfway interested in learning common lisp, but when clojure came along I actually got excited enough to do something about it.
You even say you're 'very happy' to be working in it, but I think 'an experiment in STM' is too reductionist and shallow to address the numerous use-cases that are improved by persistent data structures and the other features that clojure provides.
It's true and it happens on both sides. I've met Lisp programmers who came in by way of Clojure who openly criticize CL for its use of parentheses and its age. It's quite silly.
The age and more importantly stasis is a fair cop, especially if the Clojure programmer cares about SMP programming, where Common Lisp does not officially even have a story. Clojure was among other things designed with SMP and functional programming in mind, and thread safety is the rule rather than the exception.
If the age is a reference to Common Lisp bearing almost all the warts of mainline Lisp (minus dynamic scoping) it's also a fair cop, Scheme inspired Lisp dialects like Clojure have gained tremendously by throwing away a lot of historical baggage. Then there's some rather horrible things Symbolics forced upon CL to increase Lisp Machine Lisp compatibility, but that are hard to implement in stock hardware.
On the other hand if you don't like CL's parens, I wonder how you can like Clojure? Almost all the special form syntax is parens, and old Lispers like me are somewhat annoyed by the vectors (first class syntax with square brackets, []) used by e.g. let.
Are there very many Clojure programmers like this? Any prominent ones???
> The age and more importantly stasis is a fair cop
I don't see how threading makes "age" a valid argument. CL is a language defined by a specification. Implementations have provided threading APIs for a while now and library authors have written cross-implementation threading APIs. Without even mentioning threading in the specification it's trivial to write multi-threaded CL applications today and I think that's a strength.
In a similar fashion, C++ hadn't included a threading API until C++11 (iirc). Yet implementations provided it and library authors had filled the gap for years until a standard API was adopted into the core standard library.
If CL was a language defined by an implementation that hadn't been updated in 10 years I might agree with you.
As for syntax it's odd. Rich Hickey himself has advocated the use of syntax-literals for data-structures citing legibility as a primary concern. One familiar with CL's access to the reader and read-table would allow the programmer to implement reader macros for the same effect without losing compatibility with the rest of CL (and the standard implements a few: #() for vectors for example, '() for (QUOTE ...) etc). Either way preference of syntax is superfluous when you have programmatic access to your language's parser and yet Cljoure programmers unfamiliar with this concept advocate that syntax-literals are the way of the future and CL's lack of syntax for various constructs is a weakness. It's a non-issue.
I've written reader macros for various flavours of assemblers. It's quite versatile.
Age isn't a very good criticism. A good specification is meant to withstand the years. CL's has done a pretty good job at that.
wrt baggage though, I will concede that perhaps they specified too much in the filepath API. A conformant CL implementation today will have to support some very obscure filesystems... which can be daunting for prospective implementation developers.
There's a BIG difference in ecosystems if a system starts out with pervasive threading or doesn't. In a slightly different domain, I saw this back when I was doing NT programming in the '90s. From the start it provided threads and plenty of thread safe stuff (and plenty not, including the MCV++ Standard Template Library in 1997, although that was mostly of an initial botch of the port from the HP? code), and this made quite a difference compared to trying to write threaded programs for UNIX(TM).
If you're not going to limit yourself to copying paradigms like the Actor model I argue you're going to be in for a world of hurt, even as your ecosystem matures, because you'll almost certainly have non-thread safe stuff from the days when the community wasn't considering threading.
So all I'm saying in this argument is that Common Lisp is traversing this painful path, and will never be as optimal as it might be, because when it was cast into concrete in 1984 threads weren't part of it.
The Clojure argument for standard data structure syntax-literals, and strict limits on reader macros, is indeed legibility, defined as portability between humans. I think it's an issue, but one that I think we'll have to agree to disagree on. Although I don't see gaining CL compatibility as a goal, the foundations of the languages are too different (functional vs. multiparadigm including but not limited to functional).
I agree that age itself isn't a good criticism, I was pointing out how Common Lisp's extreme age has resulted in issues, and "age criticisms" could be interpreted that way.
This goes all the way back all the way to the very first late '50s LISP, e.g. while I personally like them, classic examples are Contents of the Address Register and Contents of the Decrement Register (car and cdr) of the vacuum tube IBM 704. More consequential are things like Lisp-2 vs. Lisp-1; maybe it's just a matter of taste and not having written enough macros in my career but I prefer the latter.
Hmmm, to sum up, one argument for Clojure is that we now known enough to create a more restrictive dialect and benefit from the good taste of Rick Hickey and now others who are helping to carry the language's torch. Callow youth though he might be, mrottenkolber is spot on when he says it's an opinionated language, and that'll certainly mean among other things that it'll not be to many experienced Lisper's taste (probably easier if you're a Schemer, though).
I harp on SMP programming because I find it, and the functional programming solutions to it, very interesting, not to mention it's just plain better for writing robust software. Closure seems to have done a good job using the latter to address the former, and gaining those other minor details guaranteed FP grants you.
Common Lisp implementations deal with threads since day zero. The non-threaded standard has not prevented dozens of implementations to provide threads. Common Lisp has man different full implementations.
Clojure is basically just one real implementation.
Clojure limiting the use of reader macros is just another example where somebody is telling me how I should use a language. It's basically as in Java. Common Lisp and Lisp in generally has favor a different root: give power to the user. Why stop there. Why not provide a fixed amount of macros and remove the user-written macro facility from the language.
IMHO Clojure's omission of reader macros is sensible: it prevents proliferation of custom syntax, which makes it harder for a human to read code and reason about reader behaviour. The Clojure reader also already has its own literal syntax for vectors and maps [] and {} (which eliminates the most common use cases for reader macros).
If you believe that standards are helpful, then surely one standard reader behaviour is a good thing?
Regular macros are a different issue: they allow creation of custom control structures that aren't possible with normal functions. That's a powerful and useful feature, as many Lisps have proved over the years.
So Clojure rejects the former (unnecessary syntax sugar, potential for confusion, dubious value of reader proliferation) and accepts the latter (additional semantic power, proven utility). I personally think that's a good trade-off. YMMV of course.
Of course, there's nothing stopping you from implementing a custom reader in Clojure if you really want reader macros. So far, nobody (to my knowledge) seems to have cared enough to do this.
NOTE: I'm not bashing Common Lisp: just pointing out that language design has real trade-offs. For me, Clojure gets the majority of these design decisions right. For others, maybe reader macros are an essential feature and Clojure therefore doesn't work. No problem, use whatever works for you.
The reader is first of all there to extend s-expression syntax to new datatypes - not for arbitrary syntax.
Btw., vectors are written as #(1 2 3) in Common Lisp.
Thus if I as a developer want to serialize my data structure to an s-expression, I can use reader macros.
New data type syntaxes does not make code much harder to read.
> If you believe that standards are helpful, then surely one standard reader behaviour is a good thing?
Sure, Common Lisp has a standard reader. An extensible one.
> Regular macros are a different issue: they allow creation of custom control structures that aren't possible with normal functions. That's a powerful and useful feature, as many Lisps have proved over the years.
Custom control structures don't make the code harder to understand? Strange.
> For me, Clojure gets the majority of these design decisions right.
For me many of these Clojure design decisions look arbitrary and some I find just wrong. But that's just me.
"Common Lisp implementations deal with threads since day zero."
Really?
Name them.
Granted, I'm not sure myself, since I left the community in the fall of 1984 when I left Goldhill (which ran on 16 bit x86 and 640KiB - minus what DOS extra took up, so not only did it not do threading, it didn't even (initially, while I was there) do lexical scoping (!)). But I heard it took some time for Symbolics to adopt Common Lisp (installed base problem), and I don't know about the other early commercial ones.
Allegro Common Lisp is rather early to have had threading on the PC platform. Did the Macintosh do threading as of 1987? What about Lucid? A quick look at the indexes of the users guides for Liquid Common Lisp, which I understand to be its current version, don't have the word thread in them.
So, you base your knowledge of Common Lisp on the fall of 1984, the same year the book Common Lisp the Language was published? Strange. What happened in the meantime? Did they just wake you up?
Liquid Common Lisp? The chapter on 'multitasking' is hard to find?
Threads are in Common Lisp usually called Processes. The Lisp Machine had them and basically the same API was used in Common Lisp implementations. Allegro CL, Lucid, LispWorks, ...
The entry points have been literally for decades functions like PROCESS-RUN-FUNCTION and MAKE-PROCESS.
> Did the Macintosh do threading as of 1987?
The Macintosh OS at that time did cooperative multitasking. It was supported by Macintosh Common Lisp. Macintosh Common Lisp supported what was possible and the old Mac OS was crippled.
Symbolics had little problem providing Common Lisp. The Symbolics Lisp Machine ran Common Lisp and ZetaLisp side by side in one Lisp. Of course you could call the scheduler functionality from within Common Lisp. Since Symbolics also developed a new scheduler, I guess the new one was written Common Lisp.
Yes, because I'd forgotten that the Lisp Machine used the word process for threads.
My knowledge is pretty much limited to the free Common Lisp implementations, since I never had a budget for a commercial one, and their threading story has not been so happy. But that's not a valid criticism of Common Lisp.
And yet it's trivial to write a highly multithreaded application with STM in most CL implementations today.
If Clojure was less inclined to differentiate itself from other Lisps and co-opting the future of the language I believe there'd be far less zealotry on both sides of the fence. IMO Clojure is just fine. I don't see the reason why it needs to persist CL FUD in order to make its case. They're both very practical implementations of Lisp after all.
FWIW, I've been in the Clojure community for a few years and see almost zero FUD about Common Lisp. The atmosphere in the Clojure community is much more about pragmatism than zealotry.
Mostly, I see a healthy respect for other Lisps and a recognition that learning from traditions is a good way to build good things for the future.
Being in the Clojure myself, I'd say the aforementioned "healthy respect" and "pragmatism" come from the fact that we all probably have migrated through at least a few languages before ending up at Clojure, which gives us a sense of perspective that keeps most of the zeal away.
> Then there's some rather horrible things Symbolics forced upon CL to increase Lisp Machine Lisp compatibility, but that are hard to implement in stock hardware.
30 years ago, maybe Today nothing of Common Lisp is hard to implement on stock hardware.
I mean hard to implement efficiently; that's still very possibly true on non-tagged hardware without custom microcode. But maybe not so we'd really notice outside of micro-benchmarks and extreme situations.
Since when was tagging on stock hardware was introduced by Common Lisp?
Don't tell me other Lisp implementations were faster than CL, because of not using tagging.
Today LispWorks, Clozure CL, SBCL, ... on my laptop run a thousand times faster than any other Lisp implementation ever did on a physical Lisp Machine. Actually they also run code much faster than Python, Ruby and most other popular scripting languages - often by a wide marging.
I think you repeat myths from 1984 where some implementors were claiming problems on small 1984 CPUs. They detected early that there were no problems compared to the Lisp Machine. You know one of the reasons the Lisp Machine was no longer popular for Lisp users from 1988 onwards? Stock hardware was a fast for many cases and much cheaper. Implementations like Lucid CL, Allegro CL and LispWorks were on workstations very competitive.
In reality, today on 64bit Intel chips, it runs just great. Even on something like an 32bit ARM, Clozure CL runs fine.
For many cases, good native Common Lisp implementations will run faster than Clojure.
I agree that the "thrush macro" is not such a good example to show the greatness of the Lisp family of language. IMHO it's a nice syntactic sugar but it doesn't bring something fundamentally new. Still IMHO, a more suited example of the power of the macros would be how to write a memoize macro that enables to cache the results of some function.
Yep, I'm aware of the Church-Turing thesis and the relationship between TM and the Lambda Calculus. I originally had a mention of it, but I removed it because I was really more focused on the RegEx -> CFG -> ? chain and I couldn't find anything that made that connection with the Lambda Calculus. Any sources that make that connection would be appreciated!
TFA doesn't actually say where Lisp fits. I rather wish some contender for The Next Mobile OS would make a "Lisp Android" - An ART-like Lisp runtime with a zygote-like fast start for processes and copy-on-write to crunch down memory use from multiple instances of the runtime.
That's where I think Lisp would really fit. But it would take a lot of unconventional thinking about Lisp implementation and APIs.
Lisp is different. It's really quite unique; it has an elegant simplicity underlying its implementation and a deep connection to the foundations of computation. Think of this, Gregor Kiczales's book Art of the Metaobject Protocol was published 23 years ago! I learned to program in Lisp 40 years ago. What other languages did I use back in those days? Assembly language (IBM 360, CDC 6600, IBM 1130, etc), PL/1, Fortran, APL, COBOL. Nobody, argues today that we should be trying out PL/1 or we should give COBOL a try. (Are there any projects on Github using these languages from our hazy, distant past?) Lisp's beauty and power have kept it alive and vital all these years. But, there's something wrong with this story.
If Lisp is really so great, why hasn't it triumphed? I use Lisp all the time: my editor needs it during periodic tune ups. However, I can't think of when I've reached for it first when I've had a choice. Python is just easier to get things done in. If my programs don't run fast enough I don't think of Lisp, I think of C or C++. Haskell is where it's at as far as programming language research goes, not Lisp.
The important observation is that it's not just me. Lisp has had time to prove itself. It made it to the finals, and it deserves the lifetime achievement award. We can honor it's beauty, it's longevity, it's power, and even it's fantastic reincarnations (Clojure), but this isn't enough. If Lisp really was the language that we should be programming in, it would have demonstrated it by now.