通往 Lisp 的道路:该选哪种 Lisp
选择“学哪种 Lisp”或“用哪种 Lisp”很快就会引出更广泛的问题:语言设计、工具链,以及人们究竟喜欢怎样思考程序。评论者从可读性、动态与静态类型、性能、宏的威力和生态成熟度等方面比较了 Common Lisp、Scheme/Racket、Clojure 等;许多人指出 Lisp 在可扩展性和 REPL 驱动的实时工作流方面很强,但在编辑器支持和长期可维护性上也有障碍。这个讨论反复强调一个主题:最适合的 Lisp 往往不取决于抽象优雅,而更取决于可用工具、宿主平台,以及你更看重稳定性、就业相关性还是实验性。
选择 Lisp 方言
- 有几位建议“先随便选一个开始”,其中 Common Lisp 和 Scheme 是主要选项。
- Scheme 因其小而干净的核心而受到称赞(适合学习、SICP、TSPL、Racket/DrRacket、Guile、Chez、Chicken、Gambit/Gerbil)。
- Common Lisp 被强调具有稳定、完整的规范、性能(例如 SBCL)、数十年前代码的可移植性,以及广泛的标准库。
- Clojure 被推荐用于实际工作、JVM/宿主生态、较低的库变动、EDN,以及 Babashka 之类的工具。
- 还提到的其他方言包括:Emacs Lisp、AutoLISP、Racket、Guile、Janet、Fennel、Jank、Jolt、Rhombus、Hylang、Gerbil,以及裸机 Lisp。
可读性、语法与风格
- 一些人觉得 Lisp 很难读,也从未完全“自然”,尤其与更传统的过程式语法相比。
- 另一些人则认为,当你在心理上忽略括号,并依赖缩进和结构化编辑之后,Lisp 会出现一个拐点,变得比其他语言更易读。
- Common Lisp 可以用非常过程式的风格来写;循环/宏(“loop”、“dotimes”等)让它感觉像熟悉的类 Algol 语言。
- 对不喜欢 s-expression 的人,提议使用替代语法(例如 Rhombus、CL 中的 Clojure 风格字面量、类似 Hiccup 的数据标记)。
宏、可扩展性与“活性”
- Common Lisp 的宏系统和 reader macro 被强调为能够支持任意可扩展语法、DSL,甚至新语言(例如 Coalton、JSON 字面量)。
- 有人认为 Lisp 宏被过度吹捧;许多宏示例在其他语言中也可以借助编译器技术实现,而且过于聪明的宏会损害可维护性。
- 也有人反驳说,在宏展开时能使用完整语言,再加上运行时编译,仍然具有独特的强大性和实用性。
- CL 和 Clojure 的“live image”开发方式(编辑正在运行的系统)与 Racket 更偏批处理编译的感觉形成对比。
规范、类型与可移植性
- ANSI Common Lisp 冻结的规范既受到称赞(稳定、长寿),也受到批评(线程、socket、Unicode、流、可扩展序列留给了不可移植的扩展;CLOS 也未完全整合)。
- CL 支持可选类型和一定程度的渐进类型,但批评者说它“类型化做得不太好”(例如列表类型过粗、没有泛型)。
- 还提到了 Scheme 的 R6RS 与 R7RS 状况,以及 OS 互操作可移植性问题,这是另一个碎片化来源。
- 一位参与者对动态语言总体上感到困扰,怀念关于程序正确性的静态保证;所提出的缓解方式(测试、REPL、实时编辑)让人觉得并不充分,而“正确”的工作流仍不清楚。
工具与学习资源
- 对许多人来说,Emacs 仍是最经典的体验;也有人非常不喜欢它,并寻找替代方案。
- 建议的工具包括:LispWorks(功能强大但对业余爱好者来说很贵)、Mine 和 Lem(新的 CL IDE)、用于 VS Code 的 OLIVE 插件、适合 Clojure 的优秀 Neovim/VS Code 配置。
- 推荐的学习路径包括:“Practical Common Lisp”、“An Introduction to Programming in Emacs Lisp”、SICP、HTDP(Racket)、“The Scheme Programming Language”、以及用于 FP 概念的 Haskell 资源。
元视角
- 有人认为 Lisp 并没有其名声所暗示的那样独特神奇;许多想法在别处也存在。
- 也有人坚持认为,异源代码性、宏、REPL 驱动开发,以及跨多种运行时的宿主互操作这一特定组合,让 Lisp 异常有效,而且从长期职业生涯来看,“通往 Lisp 的道路无处不在”。