7 ms·
To make a statement about Common Lisp from simple tutorial code is a bit much. If one looks at music software in Common Lisp, the code is on a higher level tha
by lispm 11y ago
To make a statement about Common Lisp from simple tutorial code is a bit much.
If one looks at music software in Common Lisp, the code is on a higher level than building lists like that.
> Secondly, this code tries to handle lists in the classic Lisp way, with recursion, and that's not what you typically do in Clojure.
Neither is it done in Common Lisp.
> Those 7 lines of Common Lisp compress to 2 lines of Clojure
The actual difference is that Common Lisp uses LOOP and not FOR, and that LOOP needs two nested LOOP forms:
CL-USER 11 > (defun build (list1 list2)
(loop for e1 in list1 append
(loop for e2 in list2 collect (list e1 e2))))
BUILD
CL-USER 12 > (build '(1 2) '(a b))
((1 A) (1 B) (2 A) (2 B))
Two iteration forms in a LOOP don't nest, but provide iteration bindings similar to LET* and LET:
(loop for i in '(1 2 3) for j = (expt i 2) collect (list i j))
and
(loop for i in '(1 2 3) and j in '(1 4 9) collect (list i j))
Common Lisp's ITERATE macro also needs nested forms, but slightly improved over LOOP:
ITER-USER 26 > (iterate outer (for i in '(1 2))
(iterate (for j in '(a b))
(in outer (collect (list i j)))))
((1 A) (1 B) (2 A) (2 B))
The author of Clojure knows these differences very well, since he was a heavy Common Lisp user for a few years.
> But, at the same time, if you're looking to translate stuff from other Lisps into Clojure, it'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.
That's true. Clojure is not a Lisp, but partially derived from it, with many other influences from Haskell and other languages. It's mostly incompatible to Lisp: software can't be shared or copied, it needs to be complete rewritten. Thus basic Lisp literature is only of use when it's about features which got copied. For example the book 'On Lisp' might help to understand macros in Lisp and Clojure, whereas books like 'Practical Common Lisp' or Norvig's PAIP aren't very useful for Clojure programmers.
- taeric 11y agoI'm not sure calling "Clojure not a lisp, but partially derived from it" really makes sense. That code from other lisp implementations needs rewritten to be ported, is really not that much different from how many other lisp implementations were to each other. CL and Scheme did a lot to unify things, such that any scheme should run another scheme's code. Same for any CL implementation. But, for example, running emacs lisp in any other lisp just isn't going to work.
- lispm 11y agoWell, actually Emacs Lisp and Common Lisp were derived from the same language and share a lot. CL-USER> (defun fact (n) (do* ((i n (- i 1)) (j i (* j i))) ((= i 1) j))) FACT CL-USER> (fact 15) 1307674368000 Unchanged code in Elisp... ELISP> (defun fact (n) (do* ((i n (- i 1)) (j i (* j i))) ((= i 1) j))) fact ELISP> (fact 15) 1307674368000 (#o23016735654000, #x13077775800) Elisp originally was designed as a Maclisp subset. Common Lisp was designed as a Maclisp successor.
- taeric 11y agoFair. There have been, and always will be lisps that can be copy pasted between each other. Just as you can get some implementations of programs in some assemblies that work between assemblies. That does not say anything about whether or not a language is an assembly. Just as this says nothing about whether a language is a lisp.
- lispm 11y agoA family is a social construct. It's about sharing, communicating, learning, building, inheritance. Emacs Lisp is directly in the tradition of McCarthy's Lisp. It shares names, concepts, literature, even code. Logo, Dylan, ML, Clojure don't. They were derived or inspired by Lisp, but they are now they own language family...
- 59nadir 11y agoYou're bunching Clojure in with several languages that have strayed far further from Lisp. Clojure was designed specifically with the intent of being a dialect of Lisp, which means it's explicitly not in its own language family or in any other language family than Lisp.
- lispm 11y ago> Clojure was designed specifically with the intent of being a dialect of Lisp The result of that design is that Clojure shares literally zero lines of code with other Lisps: Autolisp, ISLisp, Emacs Lisp, Standard Lisp, Common Lisp. Many basic concepts are absent, renamed or redesigned ('Atom', 'Linked List', ...). Clojure is fully incompatible to any other language with Lisp in its name. Programs have to be re-architectured, because the concepts are different: no TCO, but 'functional', different approach about side effects (-> avoid), lazy persistent datastructure at its core, different idea of OOP (-> avoid), Lisp infrastructure (-> avoid), ... There is no software I know of, which is shared. The number of tools shared is 'one': GNU Emacs. It's a different community with different goals, different software, different applications, different libraries. Just think of it: zero lines of code is shared. My problem with that broader idea of 'Lisp': it is fully vague and it has no practical implications. Sometimes it's only a marketing slogan. It has the same vague meaning like 'object-oriented' or 'Functional'. There is no consensus what OOP in a broad sense means and how it should be defined. 'Lisp' is just as useless. It does not mean that Clojure is useless or worse than Lisp. Totally not. Clojure has new ideas on data structures put to work and enabled some very productive people enjoying their tools. They are doing wonderful stuff.
- EdwardDiego 11y ago> Clojure is not a Lisp I keep seeing people make this statement, without any explanation of why. To me, hardly a heavy user of other Lisps, but with enough time spent in Common Lisp and Scheme to have an idea of what's going on, it feels pretty lispy.
- pjtr 11y agoI assume there's no official hard definition of what it means to be a Lisp. It's like "Pythonic". A warm fuzzy feeling that not everyone will share about the same things. It depends on what they consider important / good about a language. Is C++ a C? Is Oberon a Pascal? Is F# a ML? Is C# a Java? Is Go a Squeak? Is Objective-C a Smalltalk? Is Javascript a Self?
- oblio 11y agoPython actually has a definition for pythonic. PEP 20: https://www.python.org/dev/peps/pep-0020/ https://www.python.org/dev/peps/pep-0020/. Just think of it as civil law (versus common law) when interpreting it.
- 59nadir 11y ago> That's true. Clojure is not a Lisp, but partially derived from it. Clojure is a Lisp. It may not be Lisp, but it's a Lisp. Just like any nix OS is not UNIX but is a Unix OS. Clojure is most definitely a dialect of Lisp. From clojure.org: > Clojure is a dialect of Lisp, and shares with Lisp the code-as-data philosophy and a powerful macro system. The intent of the design of Clojure was clearly to be a dialect of Lisp, hence the above quote from Rich Hickey proudly displayed on their site.
- dkersten 11y agoI think the problem is that people seem to equate "Lisp" to "Common Lisp". Clojure is a Lisp, but Clojure is not Common Lisp. LISP appeared in the late 50's/early 60's. Common Lisp only appeared in the early-to-mid 80's. There were many other lisps in between and many since. Common Lisp is only one of many dialects of Lisp. Clojure is another. (Not saying that this is what lispm did in this case, (s)he seems to know a lot about lisp; rather this is a common confusion I've seen)
- hga 11y agoCommon Lisp, though, is the lineal descendant of the original LISP, so a case needs to be made for anything else like Scheme and Clojure that claim to be Lisps. I guess I'm saying it's a debatable point.
- lispm 11y agoIf Clojure is Lisp, why doesn't it run any Lisp code? Take code from any Lisp book from the past 50 years and type it into Clojure. It won't work. Even really basic Lisp code won't work. > There were many other lisps in between and many since. They all share a core language. Simple REPL in Emacs Lisp: ELISP> (defun read-eval-print-loop () (do* ((input (read) (read)) (value (eval input) (eval input))) ((equal input '(quote quit)) 'done) (print 'input>) (princ input) (print 'value>) (princ input) (print value))) read-eval-print-loop ELISP> (read-eval-print-loop) input> (mapcar (quote +) (quote (1 2 3))) value> (mapcar (quote +) (quote (1 2 3))) (1 2 3) done Now OpenLisp, an implementation of ISLisp. Code unchanged. ; OpenLisp v10.1.0 (Build: 5932) by C. Jullien [Aug 30 2014 - 07:38:27] ;; WARNING: \"startup.lsp\" file not loaded. ? (defun read-eval-print-loop () 1> (do* ((input (read) (read)) 3> (value (eval input) (eval input))) 2> ((equal input '(quote quit)) 3> 'done) 2> (print 'input>) 2> (princ input) 2> (print 'value>) 2> (princ input) 2> (print value))) ;; elapsed time = 0.000s, (0 gc). = read-eval-print-loop ? (read-eval-print-loop) ? (mapcar #'1+ '(1 2 3)) input> (mapcar #'1+ '(1 2 3))value> (mapcar #'1+ '(1 2 3))(2 3 4) The output lacks correct formatting, but generally it works. The same code unchanged in Common Lisp: CL-USER> (defun read-eval-print-loop () (do* ((input (read) (read)) (value (eval input) (eval input))) ((equal input '(quote quit)) 'done) (print 'input>) (princ input) (print 'value>) (princ input) (print value))) READ-EVAL-PRINT-LOOP CL-USER> (read-eval-print-loop) (mapcar '+ '(1 2 3)) INPUT> (MAPCAR (QUOTE +) (QUOTE (1 2 3))) VALUE> (MAPCAR (QUOTE +) (QUOTE (1 2 3))) (1 2 3) 'quit DONE Every language I would name Lisp runs this code mostly unchanged. If it does not, it is not Lisp. Then it would be Scheme, Logo, Dylan, Clojure or some other language.
- davorb 11y ago> Neither is it done in Common Lisp. LOOP is something that imho very controversial. I don't think it's fair to say that its use is idiomatic.
- wtbob 11y ago> LOOP is something that imho very controversial. No, not really: it's as controversial as Common Lisp's Lisp-n nature (which is to say, both of which are controversial amongst Scheme programmers writing Common Lisp). It's a perfectly useful macro. ITERATE is a bit more traditionally Lispy, and is an easy library away if one wants it. > I don't think it's fair to say that its use is idiomatic. Not using it is typically less clear. It's part of the standard; it's more elegant than using other parts of the standard; it's idiomatic.
- hga 11y agoEh, no, it was controversial when it was being developed in the early '80s, a lot of respectable Lispers didn't like it, thought it was too complicated and easy to get wrong. But Common Lisp also has simpler constructs like dolist that aren't, to my knowledge, "controversial", except of course as you note this paradigm isn't a Scheme sort of thing.
- deleted 11y ago[deleted]
- lispm 11y agoIt's idiomatic to use a sublanguage. Think FORMAT. CLOS. Control flows using the condition system. LOOP is just another style to extend Lisp. There are older libraries which use similar style. Simple example from Winston&Horn's book LISP for a database query language: (db-select screwdrivers with color eql red)
- mcguire 11y agoNote that Common Lisp does not require tail-call elimination, so recursion is not really a standard operation. There's no one who thinks LOOP is a crawling horror than me, but it or something like it is your only option.
- alexatkeplar 11y ago"A language is a dialect with an army [build tool] and navy [package repository]"