8 ms·
Hyperpolyglot Lisp: Common Lisp, Racket, Clojure, Emacs Lisp
- eamonnsullivan 5mo agoClojure 1.6, Emacs 24.5... These are pretty old versions, at least of those.
- db48x 5mo agoMost of the things in that table won’t change from version to version anyway.
- rahen 5mo agoEmacs Lisp is a descendant of PDP-10 MAClisp, which makes it one of the oldest Lisp dialects still actively maintained. Whether it's version 24.5 or 30.2 doesn't make much of a difference semantically.
- devin 5mo agoTo be fair I think the only real differences since 1.6 you’d see are transducer versions of some of what’s in here for Clojure. The stuff expressed here is all very basic.
- waffletower 5mo agoThere is a difference with the very first line item, though minor: "clojure --version" is available. True that transducers aren't going to be a part of this comparison.
- waffletower 5mo agoI have been a clojurist for more than a decade and I started with Clojure 1.7. 1.6 was released in 2014!
- ecto 5mo agoGreat chrestomathy! I opened a PR for my lisp, Loon: https://github.com/clarkgrubb/hyperpolyglot/pull/139 https://github.com/clarkgrubb/hyperpolyglot/pull/139
- arikrahman 5mo agoWould be interesting to see how Jank is coming along in this space as well.
- veqq 5mo agoJank's just supposed to be Clojure with full compatibility, when mature.
- sinsudo 5mo agoI know that the purpose of the page is to compare syntax of common lisp, racket, clojure, and emacs lisp. But some examples could be more idiomatic, for instance instead of (defun add (a &rest b) (if (null b) a (+ a (eval (cons '+ b))))) One should avoid eval and use endp instead of null: (defun add (a &rest b) (if (endp b) a (apply #'add (+ a (first b)) (rest b))))
- CodeArtisan 5mo agoShouldn't it be (+ a (apply + b))
- db48x 5mo agoAlmost. It should be (+ a (apply #'+ b)). Common Lisp is a Lisp-2, so a + in the argument position is assumed to be a variable named +, not the function named +, unless you specify otherwise.
- gus_massa 5mo agoNo, the idea is to assume for this example that + only can be used with two arguments and define a new function that can be used with any number of arguments.
- ludston 5mo agoWorse: Using recursion in Common Lisp isn't idiomatic, given that CL doesn't guarantee tail-call optimisation in the specification.
- dreamcompiler 5mo agoSigh. This again. All major Common Lisps support tail call optimization with proper declarations, with the exception of ABCL because it runs on the JVM. And those declarations are all identical or almost identical, so it's easy to write an implementation-specific macro to guarantee TCO if you need to do so. Some algorithms are easiest to express and read with looping constructs. For those algorithms, use looping constructs. Other algorithms are easiest to express and read with recursion. For those, use recursion. You shouldn't be afraid of recursion just because ANSI doesn't say TCO is guaranteed. You should be afraid of it if your code needs to run on ABCL, but otherwise, recur on.
- ethagnawl 5mo agoThis is really neat. Something I've been meaning to do is try putting together a cross-lisp package manager -- if only because it'd be fun. Maybe it would favor code that could be readily run or eval'd or maybe with some sort of clj/cljs type dynamic dispatch for anything implementation specific.
- sinsudo 5mo agoThe page indicates that there is not function for documentation in common lisp, but (documentation 'documentation 'function) "Return the documentation string of Doc-Type for X, or NIL if none exists. System doc-types are VARIABLE, FUNCTION, STRUCTURE, TYPE, SETF, and T. Also http://rosettacode.org for computer tasks implemented in many computer languages to allow you compare syntax and code.
- dreamcompiler 5mo agoLikewise apropos. It's an ANSI function.
- anthk 5mo agoEmacs has cl-lib https://www.gnu.org/software/emacs/manual/html_mono/cl.html https://www.gnu.org/software/emacs/manual/html_mono/cl.html
- FrustratedMonky 5mo agoNice comparison. But makes me think we'd be better off if we all just focused on a single one, and grew it, made it better. Not having 4 versions of something almost identical. Fragmentation can hurt adoption.
- db48x 5mo agoThat’s what Common Lisp is.
- MathMonkeyMan 5mo agoYou got downvoted, but you're correct. Obligatory XKCD: <https://xkcd.com/927/ https://xkcd.com/927/> Personally I prefer lisp 1 languages, like scheme. Even there, though, there was a split over r6rs, so we got a bunch of mostly-like-r5rs schemes and racket. Maybe the problem is that lisps are no longer popular enough to have a winning implementation! If there is one, though, then it's Common Lisp on SBCL.
- erichocean 5mo agoThere are deep reasons for the variations, especially around (reader) macros.
- ludston 5mo agoThey are as different from one another as Java is from C# is from JavaScript.
- FrustratedMonky 5mo agoSo, not by much?
- FergusArgyll 5mo agoAs someone who's not a programmer but has beginner - medium python & C skills. I'm in middle of learning lisp (elisp to be precise) and it feels like reading poetry. It's a transcendent experience that's hard to explain. Such beautiful concepts. Everything flows in a way it doesn't in C based langs
- vindarel 5mo agoNotes on CL: - why nothing on the "compiler" line? Everytime you load a snippet or a file with SBCL, it compiles it (to machine code). There's also compile-file. - interpreter: likewise, all code is compiled by default with SBCL, not interpreted, even in the REPL. To use the interpreter, we must do this: https://github.com/lisp-tips/lisp-tips/issues/52 https://github.com/lisp-tips/lisp-tips/issues/52 - command line program: the racket cell shows the use of -e (eval), the same can be done with any CL implementation. - since the string split line introduces cl-ppcre, one could mention cl-str :D (plug) (much terser join, trim, concat etc) - ah ok, for dates and times, flattening a list, hash-table literals… we need more libraries. - more files operations: https://lispcookbook.github.io/cl-cookbook/files.html https://lispcookbook.github.io/cl-cookbook/files.html - emacs buffers: now compare with Lem buffers 8-) - posix-getenv: I'd rather use uiop:getenv (comes in implementations). - uiop:*command-line-arguments* - exit: uiop:quit - uiop:run-program (sync) / launch-program (async) - java interop: with LispWorks or ABCL (or other libraries) my 2c
- sinsudo 5mo agoSince you are also commenting libraries, I think that FSet (1) for inmutable memory,and perhaps a comparison with clojure, and the quick-lisp package manager could be mentioned. (1) https://news.ycombinator.com/item?id=47779659 https://news.ycombinator.com/item?id=47779659
- aidenn0 5mo ago> - ah ok, for dates and times local-time has its limits (e.g. Gregorian only), but it does everything listed in this chart > flattening a list What? Isn't this[1] just fine (<s>) > hash-table literals… Since the chart is sbcl specific, this ugly mess would technically count; a more portable (but longer) version could be made similarly using #.: #.(SB-IMPL::%STUFF-HASH-TABLE (MAKE-HASH-TABLE :TEST 'EQUAL) '((:X . :Y))) > java interop: with LispWorks or ABCL (or other libraries) I've had good luck with .net/java interop using FOIL (written by Rich Hickey prior to Clojure). 1: CL-USER> (let* ((result (cons nil nil)) (tail result)) (subst-if t (constantly nil) '(a ((b(c d)) e) f) :key (lambda (x) (when (and x (atom x)) (setf (cdr tail) (cons x nil) tail (cdr tail))))) (cdr result)) => (A B C D E F)
- kickingvegas 5mo agoPerhaps related, I'm maintaining a "cheatsheet" to let Python programmers see what an Elisp equivalent to typical Python functions/methods are. https://kickingvegas.github.io/elisp-for-python/ https://kickingvegas.github.io/elisp-for-python/
- emil-lp 5mo agoAre `(push s x)` and `(push x s)` correct for push and insert, resp.?
- kickingvegas 5mo agoOh dang, thanks for catching that. Will amend.
- aidenn0 5mo agoCL list comprehension: (loop for file across "ABCDEFGH" nconc (loop for rank from 1 to 9 collect (format nil "~C~D" file rank)))
- Jach 5mo agoOr with more Python-esque syntax: (let ((files (coerce "ABCDEFGH" 'list)) (ranks (loop for r from 1 to 9 collect r))) [(format nil "~a~a" file rank) (file <- files) (rank <- ranks)]) Based on the list comprehension macro from 1991 in https://3e8.org/pub/scheme/doc/lisp-pointers/v4i2/p16-lapalme.pdf https://3e8.org/pub/scheme/doc/lisp-pointers/v4i2/p16-lapalm... that still works. (defmacro comp ((e &rest qs) l2) (if (null qs) `(cons ,e ,l2) ; rule A (let ((q1 (car qs)) (q (cdr qs))) (if (not (eq (cadr q1) '<-)) ; a generator? `(if ,q1 (comp (,e ,@q) ,l2) ,l2) ; rule B (let ((v (car q1)) ; rule C (l1 (third q1)) (h (gentemp "H-")) (us (gentemp "US-")) (us1 (gentemp "US1-"))) `(labels ((,h (,us) ; corresponds to a letrec (if (null ,us) ,l2 (let ((,v (car ,us)) (,us1 (cdr ,us))) (comp (,e ,@q) (,h ,us1)))))) (,h ,l1))))))) (defun open-bracket (stream ch) (do ((l nil) (c (read stream t nil t)(read stream t nil t))) ((eq c '|]|) `(comp ,(reverse l) ())) (push c l))) (defun closing-bracket (stream ch) '|]|) (set-macro-character #\[ #'open-bracket) (set-macro-character #\] #'closing-bracket) Supports filtering too, e.g. (let ((xs '(1 2 3 4)) (ys '(1 2 3 4))) [(+ x y) (x <- xs) (y <- ys) (evenp x) (oddp y)]) ; -> (3 5 5 7)
- aidenn0 5mo agoI didn't try macroexpanding it yet, but when I make the 9 a runtime-parameter, I eventually get a stack-overflow with SBCL not TCO-ing the "H" binding in labels. The comments make me think this is ported from scheme, which has precise TCO rules. [edit] macroexpanded: (LABELS ((H-37 (US-38) (IF (NULL US-38) NIL (LET ((FILE (CAR US-38)) (US1-39 (CDR US-38))) (LABELS ((H-43 (US-44) (IF (NULL US-44) (H-37 US1-39) (LET ((RANK (CAR US-44)) (US1-45 (CDR US-44))) (CONS (FORMAT NIL "~a~a" FILE RANK) (H-43 US1-45)))))) (H-43 RANKS)))))) (H-37 FILES))
- dfox 5mo ago> cannot start with digit Not only it can, but both CL and Emacs Lisp actually defines primitives with names that start with digit.