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, ...
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.
This was the big breaking change from Scheme that CL wasn't willing to make because it would have broken too much invaluable code.
> It's not LISP and its not Lisp either
Furthermore note the difference between "X is Lisp" and "X is _a_ Lisp".
But it's most certainly a "Lisp".
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.
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).
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).
ABCL is a CL implementation for the JVM.
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.
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.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.
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.
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.
I also haven't heard much about how easy CL's host language inter-op is to work with...
Another big thing of course is that the community is much more vibrant and welcoming than Common Lisp's.
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.
> 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.
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 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.
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.
- 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.
Slightly tongue-in-cheek talk by Uncle Bob on the topic: - https://skillsmatter.com/skillscasts/2323-bobs-last-language
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.
Although be warned that the article starts to pitch a particular implementation (LispWorks) near the end it is worth reading.
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.
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???
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.
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.
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.
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.
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.
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.
Liquid Common Lisp? The chapter on 'multitasking' is hard to find?
http://www.lispworks.com/documentation/lcl50/aug/aug-103.htm...
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.
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.
Threads in ECL:
http://ecls.sourceforge.net/new-manual/ch27.html
Threads in Clozure CL:
http://ccl.clozure.com/manual/chapter7.html#Programming-with...
Threads in SBCL:
http://www.sbcl.org/manual/index.html#Threading
ABCL support threads.
Threads in CLISP:
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.
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.
30 years ago, maybe Today nothing of Common Lisp is hard to implement on stock hardware.
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.
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!