友好的Racket入门指南
摘要
Racket友好入门,一种用于语言导向编程的Lisp方言,讲述其从Lisp起源到现代教育与研究应用的发展历程。
暂无内容
查看缓存全文
缓存时间: 2026/08/22 16:32
# Racket 语言友好入门指南
来源:https://geometridae.bearblog.dev/a-friendly-introduction-to-racket/
*2026年8月11日*
steal-your-face-plt
> “Lisp 值得学习,因为当你最终理解它时,将获得深刻的启蒙体验。” —— Eric S. Raymond
欢迎!今天你将学习一门来自编程史上最古老、最独特的语族中的语言。这门语言中代码即数据,括号是纯粹的结构,程序可以编写程序。在本教程结束时,你将能编写自己的语法。
---
## 简要历史
Lisp 诞生于**1958年**,由麻省理工学院的 John McCarthy 发明。作为参考:它是仍在使用的第二古老的高级语言(仅比1957年的 Fortran 晚一年)。Python 在1991年诞生,JavaScript 在1995年出现。Lisp 比它们早30多年,我们现在认为"现代"的许多理念都源于此:
- **垃圾回收机制**——*专门为*Lisp 发明。
- **一等函数**——将函数作为参数传递,如今已成标准。
- **REPL**(读取-求值-打印循环)——Python、Node.js 和 Julia 都有的交互式环境,就起源于 Lisp。
- **条件表达式作为值**——能返回值的`if`语句。
- **同像性**——代码*就是*语言本身的数据结构。这是关键特性。我们将在文末详细讨论。
数十年来,Lisp *一直是*人工智能领域的首选语言。在70和80年代,甚至有专门设计来直接运行 Lisp 的实体计算机:由 Symbolics 和 LMI 公司制造的**Lisp 机器**。随后"AI寒冬"来临,资金枯竭,Lisp 从明星语言变为小众语言。
但有趣的思想不会消亡,只会变异——这正是 Lisp 美学的一部分。
### 从 Lisp 到 Scheme 再到 Racket
1975年,Gerald Sussman 和 Guy Steele 创建了**Scheme**:一种极简、优雅、近乎数学化的 Lisp。Scheme 成为学术界最喜爱的*编程教学*语言(传奇教材《计算机程序的构造和解释》就使用 Scheme 编写)。
1995年,Matthias Felleisen 团队创建了**PLT Scheme**,一种为教育和编程语言研究设计的 Scheme。2010年它更名为**Racket**,如今它已远不止是 Scheme:它是一个*构建语言的语言*。其非官方格言是*面向语言的编程*:如果你的问题需要自己的语言,Racket 能让你在一个下午内构建出来。
年份|事件
---|---
1958|McCarthy 在 MIT 发明 Lisp
1975|Sussman 和 Steele 创建 Scheme
1984|Common Lisp 标准化
1995|PLT Scheme(现 Racket)诞生
2007|Clojure 诞生(JVM 上的 Lisp)
2010|PLT Scheme 更名为 Racket
今天|你,正在阅读此文,即将编写括号(激动) UwU
---
## *当今*谁在使用 Lisp?
比你想象的要多:
- **Clojure**在银行、航空公司和初创企业投入生产运行(拉丁美洲最大的数字银行 Nubank 就运行在 Clojure 上)。
- **Common Lisp**(配合 SBCL 编译器)仍活跃于专家系统、飞行规划(被 Google 收购的 ITA Software 驱动着 Google Flights)和科学计算领域。
- **Emacs Lisp**——数百万人每天使用 Lisp 却不自知,因为他们的编辑器*就是*Lisp 解释器。
- **Guile/Guix**——整个 Linux 发行版100%使用 Scheme 配置。
- **Racket**有自己的年度会议(RacketCon),活跃的学术和艺术社区,并用于语言研究、形式化验证(Rosette)、字体排印与出版(Pollen)以及全球教育领域。
- 新 Lisp 方言持续涌现:**Fennel**(编译到 Lua 的 Lisp,常用于游戏开发)、**Janet**、**Hy**(基于 Python 的 Lisp)……
## TADC 影迷的彩蛋:
TADC
> 在《神奇数字马戏团》(第8集"hjsakldfhl")中,当 Kinger 打开终端试图重置 Caine 时,可以看到 Caine(一个1996年构建的创意AI)是用 Lisp 编程的。文件名就叫`Caine-core.lisp`。
---
## 安装(5分钟)
1. 访问 https://racket-lang.org/
2. 下载适合你系统(Linux、macOS、Windows)的安装包。
3. 打开附带的**DrRacket**环境。
DrRacket 分为两个区域:顶部编写**定义**(你的程序),底部是**REPL**用于实时实验。在定义区域的第一行写入:
```racket
#lang racket
```
这行代码告诉 Racket 你使用的语言(记住:Racket 是语言工厂,必须选择一个)。
如果更喜欢终端:`racket`命令提供 REPL,`raco`是包管理器和工具命令。
---
在 REPL 中尝试:
```racket
> (+ 1 2)
3
> (* 3 (+ 2 2))
12
> (string-append "hello " "world")
"hello world"
```
Lisp 的规则可归结为一行:
> 一切都是`(操作符 参数1 参数2 ...)`。始终如此。无例外。
无需记忆运算符优先级,没有特殊语法。`(+ 1 2)`执行加法,`(if ...)`进行判断,`(define ...)`进行定义。起初看似可怕的括号,实则是绝对无任意规则约束的体现。一周后,你将不再注意到它们。
---
## 定义与函数
```racket
#lang racket
(define pi-approx 3.14159)
(define (circle-area r)
(* pi-approx r r))
(circle-area 2) ; => 12.56636
```
- 带名称的`define`创建常量。
- 带`(名称 参数...)`的`define`创建函数。
- 注释以`;`开头。
匿名函数使用`lambda`(没错,就是那个1930年代丘奇的λ演算——所有这些的理论鼻祖):
```racket
(lambda (x) (* x x)) ; 无名函数
((lambda (x) (* x x)) 5) ; => 25,直接应用
```
---
## 列表:Lisp 的核心
Lisp 是**LIS**t**P**rocessing(列表处理)的缩写。列表是基础结构:
```racket
(list 1 2 3) ; => '(1 2 3)
'(1 2 3) ; 等效形式,"引用"形式
(first '(1 2 3)) ; => 1
(rest '(1 2 3)) ; => '(2 3)
(cons 0 '(1 2 3)) ; => '(0 1 2 3)
(length '(a b c)) ; => 3
```
注意引号`'`。它告诉 Racket:*不要求值此表达式,这是数据*。记住这个细节——它将通往最终的奥秘。
### 高阶函数
这是 Racket 大放异彩的领域。将函数传递给其他函数是最自然的操作:
```racket
(map (lambda (x) (* x x)) '(1 2 3 4 5))
; => '(1 4 9 16 25)
(filter even? '(1 2 3 4 5 6))
; => '(2 4 6)
(foldl + 0 '(1 2 3 4 5))
; => 15
```
`map`变换,`filter`选择,`foldl`累积。仅这三个函数就能解决大多数列表问题,无需编写单个`for`循环。
---
## 递归:螺旋式思维
在 Lisp 中你不会想"重复N次",而是思考"基本情况是什么,如何向其推进?":
```racket
(define (factorial n)
(if (= n 0)
1
(* n (factorial (- n 1)))))
(factorial 5) ; => 120
```
为使内容更直观,让我们绘制些图形。Racket 自带图形库:
```racket
#lang racket
(require 2htdp/image)
(define (sierpinski level)
(if (= level 0)
(triangle 8 "solid" "purple")
(let ([t (sierpinski (- level 1))])
(above t (beside t t)))))
(sierpinski 6)
```
将其粘贴到 DrRacket,点击运行,即可在屏幕上看到谢尔宾斯基三角形生成。
---
## 终极奥秘:编写代码的代码
还记得引号`'`吗:它将代码转化为数据。观察:
```racket
'(+ 1 2) ; => 列表 (+ 1 2),而非数值3
(first '(+ 1 2)) ; => 符号 +
(eval '(+ 1 2)) ; => 3。你刚将数据作为代码求值了。
```
你的程序是列表。你可以构建列表。因此:**你可以用程序构建程序**。这就是**同像性**,也是 Lisp 拥有真正*宏*的原因——不是C语言的文本宏,而是在执行前接收代码并返回代码的函数。
Racket 没有`while`循环?让我们发明一个:
```racket
(define-syntax-rule (while condition body ...)
(let loop ()
(when condition
body ...
(loop))))
(define counter 0)
(while (< counter 5)
(displayln counter)
(set! counter (+ counter 1)))
```
你刚刚**扩展了语言!** 在 Lisp 中,语法由你定义。
Alan Kay 称 Lisp 是*"软件的麦克斯韦方程组"*:一个能推导出所有其他内容的极简核心。
---
## 下一步?
Kurosawa_Ruby_Holding_SICP
- **《如何设计程序》(https://htdp.org/)**——Racket 专为其设计的教材,免费在线阅读。
- **《Racket 指南》(https://docs.racket-lang.org/guide/)**——官方文档,是目前最佳文档之一。
- **《Beautiful Racket》(https://beautifulracket.com/)**——学习构建你自己的语言。
- **《SICP》**——经典中的经典,若想获得完整启蒙体验。
---
相似文章
Rhombus v1.0: 一种带有常规语法的Racket风格语言
Rhombus v1.0,一种基于Racket构建的、具有常规语法和强大宏功能的新型可扩展编程语言,已发布。
Hyperpolyglot Lisp:Common Lisp、Racket、Clojure、Emacs Lisp
一份对照参考表,比较Common Lisp、Racket、Clojure和Emacs Lisp的语法与特性。
Racket v9.3
Racket v9.3 已发布,包含多项新功能,包括 Markdown 文档生成、改进的教学语言,以及增强的包管理和 FFI 支持。
通往Lisp之路:为何选择Lisp
文章阐述了学习Lisp的理由,强调了其宏和可扩展性等独特特性,这些特性使程序员能够将语言适配到自己的问题域,并通过Blub悖论解释了为何来自能力较弱语言的程序员可能难以认识到Lisp的优势。
RacketCon 将于周六举行
RacketCon 2026 是 Racket 编程语言社区的第十六届聚会,将于周六举行,届时提供直播,演讲内容涵盖记号表示法、Typed Racket 中的类型推断,以及通过新语言 Pille 实现的底层面向语言的编程。