Lisp 诸语言巡礼

Lisp 及其众多方言——从 Common Lisp、Scheme 和 Racket,到 Clojure,以及 Gauche、Guile 和 Fennel 这类更小众的变体——被视为强大但小众的主流语言替代方案。评论者在探讨同构语法、宏、REPL 驱动开发和交互式调试之美的同时,也权衡了现实中的障碍,例如生态碎片化、非 Algol 式语法、工具怪癖、JVM 取舍,以及“只有巫师才能用”的 DSL 风险。几位贡献者认为,Lisp 在 Web 后端、脚本和 GUI 等领域可以非常务实,但社交惯性、文档质量和招聘动态,往往比语言设计更能限制其更广泛的采用。

Lisp 的流行度与采用情况

  • 许多评论者长期对 Lisp 心怀兴趣,但由于惯性、库生态和组织锁定,仍停留在主流语言(Python、Java、JS)上。
  • 其流行度通常被描述为更多是历史和社会因素,而非“设计更优”:Unix/C/C++/Java/Python 率先胜出并构建了生态;Lisp 从未在大规模上同时获得杀手级应用和厂商支持。
  • 有人认为,商业更偏爱“官僚式”语言:对普通开发者更友好、语法熟悉、能力受限;而 Lisp 则像“巫师”语言。

优点、缺点与“巫师”文化

  • 受到赞赏的特性:极简、统一的语法;宏/DSL;REPL 驱动的交互式开发;强大的可调试性;表达力强;能够嵌入并扩展语言。
  • 批评点:这种灵活性可能是一把“脚枪”——一个“巫师”就能造出难以阅读的 DSL;反引号/解引号以及宏系统常被视为主要学习门槛。
  • 反驳观点:大多数真实的 Lisp 代码都很直接,并不宏满天飞;DSL 和模式是可以学习的,而且任何语言都会出现糟糕的复杂度。

递归、不可变性与性能

  • Scheme 和某些 FP 风格强调递归,一些人觉得这很优雅,也与不可变性相契合;另一些人则认为它难读,并且与现代硬件并不匹配(分支、缺少 SIMD)。
  • Common Lisp 被视为更务实:有许多强大的迭代构造;递归主要用于天然递归的数据(如树)。
  • 尾调用优化是反复被提及的话题:Scheme 依赖它;CL 不要求它;JVM 阻止通用 TCO,但 Clojure 的 loop/recur 被视为一种务实替代方案。

实现与生态

  • Clojure:人们对其设计、不可变性、并发以及对 JVM 生态的访问充满热情。提到的缺点包括:JVM 启动慢、堆栈追踪、尾调用受限,以及平台约束(例如 Lambda 成本)。还讨论了原生变体(GraalVM、babashka、jank)。
  • Common Lisp:强大、成熟、编译器和调试器很快,但被批评为标准库命名不一致、工具细节过时,以及生态怪异。
  • Scheme 世界:碎片化以及 SRFI/R7RS 的混乱被视为重大障碍。Guile 因雄心受到称赞,但也因文档/UX 受到批评;Gauche、Chicken、Chez、Gambit、Racket、Kawa、Gauche、Janet、Fennel、Hy、femtolisp 都获得了提及,评价多为“有趣但小众”。
  • Racket 评价分化:有人认为它偏学术/面向儿童;也有人认为它高度务实且性能出色,尤其是在 Chez、强工具、宏和子语言支持加持下。

工具、REPL 与调试

  • Lisp 调试器和 REPL 驱动开发一再被称赞,认为它们在质量上明显优于打印调试或传统调试器,尤其适合对运行中的系统进行交互式修改。
  • 也有人指出,在受限制的生产环境中,连接一个实时 REPL 在实践中很困难。

工作与职业方面

  • Lisp 工作机会很少,但确实存在(尤其是 Clojure;也有一些 CL)。建议包括:关注 HN “Who’s Hiring”、小众 subreddit/Slack、“awesome Lisp companies” 列表,以及更重要的——在可行时把 Lisp 引入自己的工作场景,从而创造机会。
  • 有人声称 Lisp/F#/Haskell 经验是有利的招聘信号;也有人警告,使用小众语言通常意味着职位更少,而不是薪资更高。