If you want to learn some of the older basics of Lisp, then Emacs Lisp is fine.
Emacs Lisp: Can be used in Emacs. The development environment is included. An ancient dialect of the mainstream of Lisp. Many concepts are missing. It has many extensions for programming editors. Common Lisp and Emacs Lisp share some direct legacy (names, concepts, ...).
Generic Lisp. Lots of good books to learn. Many Lisp concepts (including OO programming) can be learned with Common Lisp. Highly recommended. Generic Lisp has the most important Lisp built-in tools, and libraries provide everything else. There is a huge amount of material that can be studied around it.
Scheme: another Lisp dialect created in the 70s. Incompatible with Emacs Lisp or Generic Lisp. Lots of great books and other learning materials. Highly recommended for teaching Lisp the basics and some more advanced things. The deeper you dig into the Scheme, the more it differs from Emacs Lisp or even Common Lisp.
Clojure: A very different dialect of Lisp. Not compatible with Common Lisp, Emacs Lisp or schema. Provides some concepts, some concepts work differently. Good books. Recommended if you want to learn some Lisp or specifically Clojure. Clojure focuses on functional and concurrent programming - very relevant topics.
If you want to learn more about basic Lisp (a Lisp that are given the typical Lisp dialect), I would recommend Common Lisp or Scheme.
My language for learning Lisp (!) Will be:
- Generic Lisp
- Scheme
- Clojure
- Emacs lisp
To give an example:
This is the McCarthy Lisp COLLAPSE function, written in 1960 (from the Lisp and Programmer Handbook , 1960, p. 101). Basically, this is because many Lisp exercises have a FLATTEN function. It takes a nested list and returns a new list with atoms in the same list.
DEFINE (((COLLAPSE,(LAMBDA,(L),(COND, ((ATOM,L),(CONS,L,NIL)) ((NULL,(CDR,L)), (COND,((ATOM,(CAR,L)),L),(T,(COLLAPSE,(CAR,L))))) (T,(APPEND,(COLLAPSE,(CAR,L)),(COLLAPSE,(CDR,L))))) ))))))
This is the General Lisp version. You can save it in uppercase or convert to lowercase. Both work.
(DEFUN COLLAPSE (L) (COND ((ATOM L) (CONS L NIL)) ((NULL (CDR L)) (COND ((ATOM (CAR L)) L) (T (COLLAPSE (CAR L))))) (T (APPEND (COLLAPSE (CAR L)) (COLLAPSE (CDR L))))))
This is basically the same. Only the function definition form has a different name and syntax. Otherwise, the code is completely identical.
Try the McCarthy example in Common Lisp :
CL-USER > (COLLAPSE '(((AB) ((C))) ((D (EF)) (G) ((H))))) (ABCDEFGH)
Performed.
Now try in Emacs Lisp using GNU Emacs. Emacs Lisp has lowercase identifiers:
ELISP> (defun collapse (l) (cond ((atom l) (cons l nil)) ((null (cdr l)) (cond ((atom (car l)) l) (t (collapse (car l))))) (t (append (collapse (car l)) (collapse (cdr l)))))) ELISP> (collapse '(((ab) ((c))) ((d (ef)) (g) ((h))))) (abcdefgh)
It works in Emacs Lisp unchanged.
You can get similar versions in Scheme (minor renaming) :.
Here in the Petite Chez scheme:
> (define collapse (lambda (l) (cond ((atom? l) (cons l '())) ((null? (cdr l)) (cond ((atom? (car l)) l) (else (collapse (car l))))) (else (append (collapse (car l)) (collapse (cdr l)))))))
We can use DEFINE to define a function. COND looks a little different. () is an empty list. ? predicates have added ? .
> (collapse '(((ab) ((c))) ((d (ef)) (g) ((h))))) (abcdefgh)
runs.
In Clojure, he would have looked different. Basically you need to rethink most of the code.
This is Clojure's own implementation of FLATTEN :
(defn flatten [x] (filter (complement sequential?) (rest (tree-seq sequential? seq x))))
You can write FLATTEN in the spirit of the Lisp version - it will still look different.
From rosetta.org :
(defn flatten [coll] (lazy-seq (when-let [s (seq coll)] (if (coll? (first s)) (concat (flatten (first s)) (flatten (rest s))) (cons (first s) (flatten (rest s)))))))
The names are different, the syntax is different, the semantics are different (works with lazy sequences instead of lists).
Dialects such as Common Lisp, Emacs Lisp, Visual Lisp, ISLISP and others try to preserve the legacy.
Dialects like Scheme or Clojure felt unconnected with names and syntax. They were introduced in different directions. The schema still provides direct versions of old functionality. Clojure no. Clojure programmers do not consider this a flaw.