使用Clojure约一个月后的感想
摘要
作者分享了学习Clojure一个月的体验,将其与Common Lisp和Scheme进行比较,并赞赏其一致性和务实设计。
暂无内容
查看缓存全文
缓存时间: 2026/06/02 21:34
# 使用Clojure约一个月后的感想
来源:https://www.acdw.net/clojure/
我现在用Clojure生成这个网站(是的,*就在*我用GNU Make和shell重写(https://www.acdw.net/things-i-like-about-my-site/)它之后;我有问题,行了吧?)。按照个人传统,我用**编写静态站点生成器**作为项目来尝试并学习Clojure这个新语言。虽然我曾嘲笑Clojure的繁多语法(*三种*括号?!),但事实证明它相当顺手且强大。以下是我玩Clojure约一个月后的印象。
## 我喜欢的东西
### 比Common Lisp更一致
Common Lisp(https://lisp-lang.org/)之所以得名,是因为它是80年代初几乎所有现存Lisp的折衷产物。因此,它是编程范式和命名方案的奇怪混合。例如,不用`map`将函数应用到列表,而是用`mapcar`。不用`filter`,而是写`remove-if-not`,带有双重否定的混乱。总的来说,Common Lisp有强烈的委员会设计感,这说得通,因为它确实如此。
由于Clojure更新且是一人的心血结晶,它作为语言更一致。例如,`seq`抽象意味着我通常不必关心处理的是哪种序列。不必记住`aref`用于数组、`nth`用于列表,我只用`nth`处理所有东西。这也让映射更容易:不必记住
``
;; 这是真正的语法!
(loop for k being the hash-keys
using (hash-value v) of hash-table
...)
;; 好吧,你也可以用
(maphash (lambda (k v) ...) hash-table)
``
我可以直接调用`(map (fn [[k v] ...]) hash-table)`就完事了。记住,`map`适用于任何集合。
相等性也是:不必记住`eq`、`eql`、`equal`、`equalp`以及更多类型特定的细微区别,我只用`=`(或者比较数值时用`==`,或者用`identical?`检查值是否相同)。公平地说,有一些注意事项(https://clojure.org/guides/equality),但一个月内我没遇到它们。学习Lisp时,我必须马上学会不同的相等形式。
### 比Scheme“功能更齐全”
Scheme也是委员会构建的,但你可以说它甚至比Clojure更一致。然而,这种“一致”好比自行车的一致:它包含很少的人体工学设计,将语言削减到最基础的骨架。实际上,Scheme报告的每个修订版的引言都这样开头:
> 编程语言的设计不应是堆积特性,而是消除使额外特性显得必要的弱点和限制。
Scheme拥护者常吹嘘R5RS规范(https://standards.scheme.org/official/r5rs.pdf)只有50页,这令人印象深刻,但基本功能如错误处理、文件处理甚至*哈希表*都从核心语言中缺失。虽然R6RS(https://standards.scheme.org/official/r6rs.pdf)增加了大量功能,但也造成了社区的巨大分裂,R7RS试图弥合,但进度缓慢。
Scheme就像一颗美丽的宝石,是纯粹编程理想的实现。而Clojure则是务实的:它有一个庞大的标准库,并且托管在JVM上,所以很可能有你工作领域所需的库。特别是作为业余程序员,我很欣赏这个生态系统。
### 易用的数据结构
最初吸引我接触Lisp的一点是它是一种“一切皆是”的语言。你知道,比如
- **Lua**:一切皆是表
- **Tcl**:一切皆是字符串
- **Lisp**:一切皆是列表
我就喜欢那种有一个大创意并将其贯彻到底的语言。
然而,在“现实生活”中,并非一切皆是列表。例如,有向量(随机访问列表)或字典(关联列表)。非Clojure的Lisp也有这些,但Clojure将它们提升为一等公民且易用。这是我最难喜欢Clojure的地方,因为我*真的*喜欢Lisp的“一切皆是列表”。但Clojure的四种基本数据类型——列表(耶!)、向量、哈希映射和集合——选择得很好,且核心语言平等对待它们,这是它们易用的关键。
## 我遇到的困难
当然,没有编程语言是完美的,到目前为止我发现Clojure有一些痛点。
### 语法太多
我保证我不是在开玩笑。我真的很喜欢Lisp语法的一致性:全是括号和空格。据我所知,唯一*更少*语法的语言是Forth。
尽管它是Lisp(别@我),Clojure比Scheme有更多的语法。有`()`、`[]`、`{}`和`#{}`用于序列;`.`和`/`在符号名称中有特殊含义;老实说,有段时间让我极为反感的是反引号语法`~`。我真的很喜欢`和 ,`的对称性!
不过,我承认随着时间推移我习惯了这种语法,甚至现在欣赏它(见上文)。我确实希望有一种更简单的方法来移动在`]}]})})`这样的块结束处。
### 我不懂Java
Clojure大力宣传它是一种*托管*语言,即运行在预建运行时上的语言。对于原版Clojure,这个运行时是JVM,据大家说是一个优秀且快速的运行时。然而,我对Java一*无所知*,只知道它据说冗长。使用Clojure的头几周,我没有太大的学习Java的需求,但我应该学习它的感觉一直存在。至少我(大部分)弄清了互操作的调用约定。
## 我打算继续使用Clojure一段时间
综上所述,我打算暂时继续使用Clojure。它有趣、相当易用,而且借助babashka(https://babashka.org/)等项目,它快速且适合脚本编写。另外,我认为更熟悉Java生态从来不是坏事。
为了获得比编写站点构建系统更多的经验,我正在用Clojure做Project Euler(https://projecteuler.net/)。用这个代码成为我的欧拉朋友:
``
2304741_7MlSvxoUOKyle32IQjYszcAAsJDCVji1
``
相似文章
@freeCodeCamp: Clojure 是一种函数式编程语言,能改变你对编写代码的思考方式。在这份互动指南…
一份互动指南,通过动画代码回放和动手练习介绍 Clojure 编程,涵盖函数、不可变数据、递归等。
Jolt:在Chez Scheme上运行Clojure
Jolt是一个新的Clojure实现,目标平台为Chez Scheme,旨在提供即插即用的替代方案,具有快速启动和低内存占用,利用Chez的JIT和GC来避免JVM的开销。
Hyperpolyglot Lisp:Common Lisp、Racket、Clojure、Emacs Lisp
一份对照参考表,比较Common Lisp、Racket、Clojure和Emacs Lisp的语法与特性。
Clojure 速度几乎媲美 C(需借助一些优化)
本文详细介绍了 Clojure 如何借助 JVM 的 Vector API 和精心优化,在 3D 压力测试中达到接近 C 的帧率(仅差 20%),展示了动态语言在热循环中也能接近底层性能。
基于Go的Clojure
Glojure是一个开源的、基于Go的Clojure语言解释器,能够无缝访问Go库,并允许嵌入到Go应用程序中。它目前处于早期开发阶段,但已用于业余项目。