如果您想学习 Lisp 的一些较旧的基础知识,那么 Emacs Lisp 就可以了。
Emacs Lisp:可以在Emacs中使用。包括开发环境。主流 Lisp 的较旧方言。缺乏很多概念。有许多编辑器编程的扩展。 Common Lisp 和 Emacs Lisp 共享一些直接的遗产(命名、概念……)。
通用 Lisp。很多好书值得学习。许多 Lisp 概念(包括 OO 编程)可以通过 Common Lisp 来学习。强烈推荐。 Common Lisp 内置了最重要的 Lisp 工具,库提供了其余的功能。围绕它有很多可以学习的东西。
方案:70 年代创建的不同 Lisp 方言。不直接与 Emacs Lisp 或 Common Lisp 兼容。许多优秀的书籍和其他教程材料。强烈推荐学习 Lisp 基础知识和一些更高级的东西。你研究得越深入,Scheme 看起来就越不同于 Emacs Lisp 甚至 Common Lisp。
Clojure:非常不同的 Lisp 方言。与 Common Lisp、Emacs Lisp 或 Scheme 不兼容。共享一些概念,一些概念的工作方式不同。好书。如果您想学习一些 Lisp 或特别是 Clojure,推荐使用。 Clojure 强调函数式编程和并发编程——非常相关的主题。
如果你想学习更主流的 Lisp(具有典型 Lisp 方言外观和感觉的 Lisp),我会推荐 Common Lisp 或 Scheme。
我学习 Lisp (!) 的语言偏好是:
- 通用语言
- Scheme
- Clojure
- Emacs Lisp
举个例子:
这是COLLAPSE
函数来自麦卡锡的口齿不清,写于 1960 年(来自Lisp I 程序员手册,1960 年 http://www.softwarepreservation.org/projects/LISP/book/LISP%20I%20Programmers%20Manual.pdf,第 101 页)。这基本上就是许多 Lisp 练习中的内容FLATTEN
功能。它接受一个嵌套列表并返回一个新列表,其中原子位于单个列表中。
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)))))
))))))
这是通用语言版本。您可以将其保留为大写或将其转换为小写。两者都有效。
(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))))))
基本上是一样的。只是定义函数的形式有不同的名称和语法。否则代码是完全相同的。
尝试麦卡锡的例子通用语言:
CL-USER > (COLLAPSE '(((A B) ((C))) ((D (E F)) (G) ((H)))))
(A B C D E F G H)
It runs.
现在让我们尝试一下Emacs Lisp,使用 GNU Emacs。 Emacs Lisp 有小写标识符:
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)
它运行在Emacs Lisp无需更改。
您可以获得类似的版本Scheme(小改名):。
Here in 小厨房计划:
> (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)))))))
我们可以用DEFINE
定义一个函数。COND
看起来略有不同。()
是空列表。谓词有一个?
added.
> (collapse '(((a b) ((c))) ((d (e f)) (g) ((h)))))
(a b c d e f g h)
Runs.
在 Clojure 中它看起来会有所不同。基本上你必须重新考虑大部分代码。
这是Clojure自己的实现flatten
:
(defn flatten
[x]
(filter (complement sequential?)
(rest (tree-seq sequential? seq x))))
你可以写一个flatten
本着 Lisp 版本的精神——它看起来仍然不同。
From 罗塞塔网站 http://rosettacode.org/wiki/Flatten_a_list#Clojure:
(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)))))))
名称不同,语法不同,语义不同(适用于惰性序列而不是列表)。
Common Lisp、Emacs Lisp、Visual Lisp、ISLISP 等方言试图保留传统。
像Scheme 或Clojure 这样的方言感觉不受名称和语法的约束。他们在各个方向进行了创新。 Scheme 仍然提供旧功能的直接版本。 Clojure 没有。 Clojure 程序员不会认为这是一个缺点。