9

Is there any synergy between learning different Lisp languages? I'm currently learning Emacs Lisp, as it is immediately useful in my daily Emacs usage, however i'm fascinated with all Lisps, so maybe someday i will learn and use others. Will learning Emacs Lisp help me, when i start digging in Common Lisp, Scheme or Clojure? In other words, will it be for me like learning a completely new language, or some notions and paradigms are common? I'm also interested in comparison of unique differences between the Lisps, which will be a problem, when i come from one Lisp to another.

In How to go about learning Common Lisp and Emacs Lisp? it is mentioned that there will be "wastage", but it is not elaborated, to what degree.

Community
  • 1
  • 1
Mirzhan Irkegulov
  • 17,660
  • 12
  • 105
  • 166

2 Answers2

18

If you want to learn some older basics of Lisp, then Emacs Lisp is fine.

  • Emacs Lisp: can be used in Emacs. Development environment included. Older dialect of the mainstream Lisp. Lacks a lot of concepts. Has many extensions for editor programming. Common Lisp and Emacs Lisp share some direct heritage (naming, concepts, ...).

  • Common Lisp. Lots of good books to learn from. Lots of Lisp concepts (including OO programming) can be learned with Common Lisp. Highly recommended. Common Lisp has the most important Lisp facilities built-in and libraries provide the rest. There is a large amount of stuff which can be learned around it.

  • Scheme: different Lisp dialect created in the 70s. Not directly compatible with Emacs Lisp or Common Lisp. Lots of excellent books and other tutorial material. Highly recommended for learning Lisp basics and some more advanced things. The deeper you dig into Scheme the more it looks different from Emacs Lisp or even Common Lisp.

  • Clojure: very different Lisp dialect. Not compatible with Common Lisp, Emacs Lisp or Scheme. Shares some concepts, some concepts work differently. Good books. Recommended if you want to learn some Lisp or specially Clojure. Clojure puts emphasis on functional and concurrent programming - very relevant topics.

If you want to learn more mainstream Lisp (a Lisp that with a look and feel of a typical Lisp dialect), I would recommend Common Lisp or Scheme.

My language preference for learning Lisp (!) would be:

  1. Common Lisp
  2. Scheme
  3. Clojure
  4. Emacs Lisp

To give you an example:

This is the COLLAPSE function from McCarthy's Lisp, written in 1960 (from the Lisp I Programmer's manual, 1960, page 101). It is basically what in many Lisp exercises is the FLATTEN function. It takes a nested list and returns a new list with the atoms in a single 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 Common Lisp version. You can keep it in uppercase or convert it to lowercase. Both works.

(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))))))

It is basically the same. Only the form for defining functions has a different name and syntax. Otherwise the code is completely identical.

Try McCarthy's example in Common Lisp:

CL-USER > (COLLAPSE '(((A B) ((C))) ((D (E F)) (G) ((H)))))
(A B C D E F G H)

It runs.

Now let's try it 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 '(((a b) ((c))) ((d (e f)) (g) ((h)))))
(a b c d e f g h)

It runs in Emacs Lisp without changes.

You can get similar versions going in Scheme (minor renamings):.

Here in 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 slightly different. () is the empty list. Predicates have an ? added.

> (collapse '(((a b) ((c))) ((d (e f)) (g) ((h)))))
(a b c d e f g h)

Runs.

In Clojure it would look different. Basically you have to rethink much 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 a flatten in spirit of the Lisp version - it would 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)))))))

Names are different, syntax is different, semantics is different (works on lazy sequences instead of lists).

Dialects like Common Lisp, Emacs Lisp, Visual Lisp, ISLISP and others try to keep the heritage.

Dialects like Scheme or Clojure felt not bound to the names and the syntax. They innovated in various directions. Scheme still provides direct versions of the old functionality. Clojure does not. Clojure programmers won't see this as an disadvantage.

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
  • 2
    Hmm. The only issue I take with this preference order is that it doesn't seem to prioritize immediate practical usability -- one area where Clojure shines; it's easy to find practical opportunities for using a JVM-based language in the workplace (and while some JVM-based Scheme implementations exist, few if any have comparable interop), and the breadth of libraries available for Clojure is far better than what's available for any particular Scheme implementation (fragmentation in that world becomes quite unfortunate when one starts trying to do practical work). – Charles Duffy Jun 28 '12 at 12:29
  • 6
    Yes, I strongly disagree with Rainer that Common Lisp / Scheme is the "more mainstream" Lisp. Don't get me wrong, I love CL, but Clojure is by far the most "real world" Lisp these days. Compare for example the difficulty of using ASDF with the ease of Leiningen/Clojars (and equally simple access to all Java maven repos). CL development practices are a bit backward, for example everyone using the latest trunk of every lib. Clojure libs tend to be well-tested, versioned, on github / straightforward to contribute to. CL libs are typically lone-wolf hobby projects, last updated a few years ago – rplevy Jun 28 '12 at 14:46
  • 2
    @CharlesDuffy: I strongly disagree, Common Lisp is focus on usuability. If you want to interact with the JVM look at [ABCL](http://common-lisp.net/project/armedbear/), if you want to interact with C look at [CFFI](http://common-lisp.net/project/cffi/). And [Practical Common Lisp](http://common-lisp.net/project/cffi/) is a great tutorial. – Daimrod Jun 28 '12 at 15:19
  • 1
    @RainerJoswig indeed, there are many Scheme implementations for the JVM -- but as I said, few if any have comparable interop. Clojure's Java interop supports features such as decorators which were only added to the JVM quite recently; I don't know of any JVM-based schemes which have been as effective at keeping up. – Charles Duffy Jun 28 '12 at 16:15
  • @RainerJoswig ...that said, I agree wholeheartedly in terms of CL being a more typical LISP than Clojure -- and if your end goal and motivation is to learn all the LISPs, as opposed to being able to find something you can use in your day job sooner rather than later and grow your skillset from there, it can indeed be the Right Thing. – Charles Duffy Jun 28 '12 at 16:18
  • 2
    @Daimrod to be fair ABCL has a developer community of about 10 people, whereas Clojure has enormous momentum with a community of thousands of developers, and a sizable number of commercial deployments. – rplevy Jun 28 '12 at 16:21
  • 1
    @RainerJoswig Re-reading your exact words, I do somewhat agree, especially a few years ago, but I think of Clojure as the new standard for Lisps. To me almost all of Clojure's core features (immutability, concurrency features, the whole approach to identity and state) constitute advances over older Lisps rather than special-case nice deviations. I personally have little to no need anymore for the traditional dialects (and CL was my favorite programming language prior to Clojure). – rplevy Jun 28 '12 at 16:30
  • @rplevy: ABCL isn't another Lisp-like dialect, it's an implementation of Common Lisp. And I didn't understand the point you're trying to make about the size of the community. What are you talking about? The number of core-dev? the number of users? – Daimrod Jun 28 '12 at 16:46
  • with all due respect, this discussion is irrelevant to the topic, so i propose to unify everything you argued into a coherent edit to the post, and then delete the comments. – Mirzhan Irkegulov Jun 28 '12 at 19:33
15

Yes - it is significantly easier to pick up a new Lisp if you know one already.

Reasons:

  • You'll understand the concept of "code is data" and metaprogramming in a homoiconic language (this is arguably the biggest single thing that makes Lisps unique / distinctive from other languages)
  • You'll be able to read Lisp syntax much more easily. It takes a few weeks to get to the point where you "see" the structure of Lisp code, but after that point it gets much easier. You start to ignore the parentheses after a while.
  • The development style is similar, interacting with a running environment using a REPL
  • They share common idioms, e.g. the use of lists and various functional programming techniques
mikera
  • 105,238
  • 25
  • 256
  • 415