TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

One Major Difference Between Clojure and Common Lisp

119 pointsby muriithiover 9 years ago

14 comments

thomover 9 years ago
This doesn&#x27;t seem like a useful comparison, analysis or conclusion. Clojure is philosophically a Lisp, but as others have pointed out, it isn&#x27;t usefully the same language as any other Lisp that preceded it or exists today. If this particular example is useful to people who might otherwise think they could reuse existing Lisp code, then I suppose it&#x27;s saved some effort, but that just seems like a straw man.<p>Either way, if you get the terminal condition of a recursive function wrong, you will blow the stack. It&#x27;s true Clojure isn&#x27;t built to do TCO, but that&#x27;s a non-sequitur. The idea that you don&#x27;t typically use recursion in Clojure is ridiculous - for is a macro, it&#x27;s syntactic sugar over Clojure&#x27;s recursion primitives, loop and recur. Even if you didn&#x27;t want to use that, change the nil? check to empty? and it works. I&#x27;m not going to claim that Clojure&#x27;s list&#x2F;sequence semantics are necessarily the cleanest (the empty _sequence_ in Clojure is nil, an empty list&#x2F;vector&#x2F;set etc is not), but they&#x27;re not hard to learn if you make any effort at all. Again, your existing Lisp experience may or may not help you understand Clojure&#x27;s data structures, but I am surprised that this is a surprise to anybody.
评论 #10208082 未加载
评论 #10211986 未加载
评论 #10208050 未加载
lispmover 9 years ago
To make a statement about Common Lisp from simple tutorial code is a bit much.<p>If one looks at music software in Common Lisp, the code is on a higher level than building lists like that.<p>&gt; Secondly, this code tries to handle lists in the classic Lisp way, with recursion, and that&#x27;s not what you typically do in Clojure.<p>Neither is it done in Common Lisp.<p>&gt; Those 7 lines of Common Lisp compress to 2 lines of Clojure<p>The actual difference is that Common Lisp uses LOOP and not FOR, and that LOOP needs two nested LOOP forms:<p><pre><code> CL-USER 11 &gt; (defun build (list1 list2) (loop for e1 in list1 append (loop for e2 in list2 collect (list e1 e2)))) BUILD CL-USER 12 &gt; (build &#x27;(1 2) &#x27;(a b)) ((1 A) (1 B) (2 A) (2 B)) </code></pre> Two iteration forms in a LOOP don&#x27;t nest, but provide iteration bindings similar to LET* and LET:<p><pre><code> (loop for i in &#x27;(1 2 3) for j = (expt i 2) collect (list i j)) </code></pre> and<p><pre><code> (loop for i in &#x27;(1 2 3) and j in &#x27;(1 4 9) collect (list i j)) </code></pre> Common Lisp&#x27;s ITERATE macro also needs nested forms, but slightly improved over LOOP:<p><pre><code> ITER-USER 26 &gt; (iterate outer (for i in &#x27;(1 2)) (iterate (for j in &#x27;(a b)) (in outer (collect (list i j))))) ((1 A) (1 B) (2 A) (2 B)) </code></pre> The author of Clojure knows these differences very well, since he was a heavy Common Lisp user for a few years.<p>&gt; But, at the same time, if you&#x27;re looking to translate stuff from other Lisps into Clojure, it&#x27;s not going to be just copying and pasting. Beyond inconsequential, dialect-level differences like defn vs. defun, there are deeper differences which steepen the learning curve a little.<p>That&#x27;s true. Clojure is not a Lisp, but partially derived from it, with many other influences from Haskell and other languages. It&#x27;s mostly incompatible to Lisp: software can&#x27;t be shared or copied, it needs to be complete rewritten. Thus basic Lisp literature is only of use when it&#x27;s about features which got copied. For example the book &#x27;On Lisp&#x27; might help to understand macros in Lisp and Clojure, whereas books like &#x27;Practical Common Lisp&#x27; or Norvig&#x27;s PAIP aren&#x27;t very useful for Clojure programmers.
评论 #10207560 未加载
评论 #10207360 未加载
评论 #10207435 未加载
评论 #10207895 未加载
评论 #10207890 未加载
devinover 9 years ago
The conclusion of this article is: &quot;Clojure is not the same as Common Lisp.&quot; Well, yeah, it&#x27;s not the exact same language. How is this surprising?<p>I wish the author would have spent a little bit more time researching. The comparison is just plain sloppy. Why is Clojure&#x27;s `recur` not mentioned, for instance? This is documentation that&#x27;s not that difficult to find by googling, and is mentioned in (I believe) every Clojure book available.
评论 #10207613 未加载
raspasovover 9 years ago
From my perspective, the three distinguishing features of Clojure from other languages&#x2F;Lisps in general are:<p>1. It&#x27;s a lisp, which means homoiconic, i.e. build software just like Lego (different from non-lisps)<p>2. Immutability and purity in the core library + sane, managed concurrency via atoms, refs, core.async, i.e. write serious multithreaded code without putting your hair on fire; helps on the front-end via ClojureScript as well (different from most other Lisps)<p>3. The JVM, which means very good performance in the general case + build once, run everyone + a lot of libraries
wtbobover 9 years ago
The Common Lisp version he has is pretty poor; I think this is more idiomatic, and is two lines as well:<p><pre><code> (defun build (list1 list2) (loop for x in list1 append (loop for y in list2 collect `(,x ,y)))) </code></pre> or:<p><pre><code> (defun build (list1 list2) (mapcan (lambda (x) (mapcar (lambda (y) `(,x ,y)) list2)) list1)) </code></pre> Still more verbose, of course, but not at all bad.
treerexover 9 years ago
Lisp != Common Lisp. The very thought that you can cut-n-paste code from one Lisp dialect to another is daft. The author obviously didn&#x27;t take the time to acquaint themselves with the basics of Clojure.<p>The lack of TCO in JVM hosted languages is besides the point.<p>It is also possible for the Clojure compiler to do TCO in certain cases: Rich Hickey made the conscious decision to not do it.
评论 #10207199 未加载
评论 #10207001 未加载
评论 #10207438 未加载
codecurveover 9 years ago
For all the gripes surrounding the lack of TCO on the JVM, Clojure really does provide a great set of tools to deal with iteration in a functional way. It&#x27;s a rare thing when I need to fall back to using loop &amp; recur.
kzhahouover 9 years ago
I&#x27;m not a clojure developer, but I&#x27;m intrigued.<p>I was gonna post the question &quot;Why should I learn clojure?&quot; but that&#x27;s easy to google for and get good articles.<p>I was then gonna post &quot;What&#x27;s a good book for learning Clojure?&quot; but I can get that on Quora.<p>So my real question is: what can I read about Clojure that will get me up to speed on its unique awesomeness? I don&#x27;t need a tutorial that shows me how to add two ints or invoke a function. Show me the good stuff!
评论 #10207121 未加载
评论 #10207362 未加载
评论 #10207104 未加载
评论 #10207148 未加载
评论 #10207143 未加载
评论 #10207142 未加载
kylloover 9 years ago
This is not a Clojure problem, it&#x27;s a JVM problem--no tail call optimization. Armed Bear Common Lisp has the exact same limitation.
评论 #10206949 未加载
评论 #10207049 未加载
PuercoPopover 9 years ago
His build implementation uses tail recursion which is not preferred in CL. One can build in a similar way that as shown at the end.<p><pre><code> (defun build (list-1 list-2) (loop :for elem-1 :in list-1 :for elem-2 :in list-2 :collect (list elem-1 elem-2))) </code></pre> A much bigger difference imho between Clojure and Common Lisp is that the former is built on abstractions, conj, while the latter is built on concrete cons cells. There are more other significant differences but I don&#x27;t want to flame&#x2F;argue.
评论 #10207430 未加载
nemoniacover 9 years ago
The reason why some people say that Clojure isn&#x27;t a lisp is that some of its design decisions such as those mentioned in the blog posting detract from the essence of lispiness. It goes too far to say that it&#x27;s not a lisp but it&#x27;s certainly less lispy than Common Lisp or Scheme.
dunkelheitover 9 years ago
What is the name for illustrating the point with deliberately unrelated example? His clojure code fails because he did not swap nil? for empty? (and he even states this in the article) but he then uses it to illustrate the absence of TCO in clojure.
评论 #10207960 未加载
Grue3over 9 years ago
I might be wrong, but the biggest difference is that lists are immutable in Clojure which makes some data structures which are based on shared conses difficult to construct, or less efficient.
hgaover 9 years ago
This is why I call Clojure a &quot;Lisp&quot;, whereas I somewhat pedantically refer to previous languages in this family as &quot;LISPs&quot;, as originally coined from &quot;LISt Processor&quot;.<p>But it&#x27;s still a Lisp, I went straight from old half-remembered mainline LISP and Scheme to Clojure in a recent small web server project without difficultly. The dynamic style of development is the same as is the typing, if you&#x27;re not using lists, then the OPs problems don&#x27;t come up (idiomatic Clojure web programming uses maps, key value pairs), the syntax is still s-expressions, albeit polluted by arrays denoted with square brackets where it makes sense.<p>And I believe the article is wrong in one sense, the JVM treats non-tail recursion like other languages, growing the stack. It&#x27;s tail call optimization (TCO) that&#x27;s the issue: mandatory in Scheme, don&#x27;t know about its prevalence in Common Lisp implementations, and it&#x27;s awkward in Clojure but wasn&#x27;t much of a jump from SICP for the typical cases. And I think it might be a good idea to require signaling when you intend to tail recurse, it&#x27;s easier and much quicker to find in compilation than when you blow the stack running it.
评论 #10206980 未加载