Racket 友好入门:一门能造语言的 Lisp

“Lisp值得学习,因为当你最终掌握它时,将获得深刻的启迪体验。”——埃里克·S·雷蒙德


欢迎。今天你将学习一种来自编程史上最古老且最独特的语言家族之一。一种代码是数据,括号是纯结构,程序可以写程序的语言。完成这个教程时,你就能写出自己的语法。

一点历史

Lisp 出生于1958由麻省理工学院的约翰·麦卡锡发明。作为背景说明:它是仍在使用的第二古老的高级语言(只有1957年的Fortran比它早一年)。

Python于1991年加入。1995年启用JavaScript。Lisp比他们早了30多年,而我们现在认为“现代”的几个想法就是在那里诞生的:

  • 垃圾收集—— 发明对于口齿不清。
  • 一类函数—— 通过函数作为参数传递,现已成为所有地方的标准。
  • The REPL—— Python、Node 和 Julia 今天都在 Lisp 中开始的交互式读-评估-打印循环。
  • 条件句作为表达式——if返回一个值。
  • 同质性—— 代码是语言本身的数据结构。这是最重要的。我们最后再回来谈。

几十年来,Lisp 一直存在该人工智能的语言。在70年代和80年代,曾有物理计算机设计用于直接运行Lisp::Lisp 机器由Symbolics和LMI共同制造。

随后到来了“人工智能冬天”,资金枯竭,Lisp从明星变成了邪典语言。

但有趣的想法不会消失,它们会变异,这正是口齿不清的魅力所在。

从Lisp到Scheme再到Racket

1975年,杰拉尔德·萨斯曼和盖伊·斯蒂尔创立了方案:一种极简、优雅、几乎数学化的Lisp。Scheme 成为学术界最喜爱的语言教学编程(传奇之书)SICP《计算机程序的结构与解释》用Scheme编写)。

1995年,Matthias Felleisen的乐团成立了PLT计划,一个旨在教育和编程语言研究的方案。2010年更名敲诈如今,它远不止是一个方案:它是一种用于构建语言的语言。

其非官方座右铭是面向语言的编程如果你的问题需要独立的语言,Racket让你在一个下午内就能建立一个。

年份 事件
1958 麦卡锡在麻省理工发明了Lisp
1975 萨斯曼和斯蒂尔创造了Scheme
1984 通用Lisp是标准化的
1995 PLT计划(现为Racket)诞生
2007 Clojure诞生(JVM上的Lisp)
2010 PLT计划更名为Racket
现今 你,正在读这段话,准备写括号 UwU

谁用Lisp现今?

比你想象的还要多:

  • 克洛尤尔在银行、航空公司和初创企业中运行(拉丁美洲最大的数字银行Nubank运行于Clojure上)。
  • 常见口齿不清(使用SBCL编译器)仍然活跃于专家系统、飞行计划(ITA软件,被谷歌收购,支持谷歌飞行)和科学计算领域。
  • Emacs Lisp——每天有数百万人在不知情的情况下运行Lisp,因为他们的编辑器是一个Lisp翻译器。
  • 狡诈/粉笔——一个100%配置在Scheme中的整个Linux发行版。
  • 敲诈拥有自己的年度会议(RacketCon),一个活跃的学术和艺术社区,并被用于语言研究、形式验证(Rosette)、排版与出版(Pollen)以及全球范围内的教育。
  • 而且新的Lisp不断出现:茴香(一种编译成Lua的Lisp,游戏中很受欢迎),珍妮特,也就是说,(Python上的Lisp)......

给TADC粉丝的彩蛋:

在惊奇数字马戏团(第8集,“hjsakldfhl”),当金格打开终端试图重置凯恩时,你可以看到凯恩(1996年建造的创造性人工智能)被编程为Lisp。文件字面上的名字就是Caine-core.lisp.

安装(5分钟)

  1. 前往https://racket-lang.org
  2. 下载适用于你系统(Linux、macOS、Windows)的安装程序。
  3. 开门DrRacket,包括随之而来的环境。

DrRacket有两个区域:顶部你写下你的定义(你的程序),底部有REPL为了现场实验。在定义区域的第一行,写下:

#lang racket

这句话告诉Racket你用的是哪种语言(记住:Racket是语言工厂,你得选一种)。

如果你更喜欢终端:racket指令会给你一个REPL,并且raco是包管理器和工具命令。

第一次接触:一切都是一种表达

在REPL中,试试:

> (+ 1 2)
3
> (* 3 (+ 2 2))
12
> (string-append "hello " "world")
"hello world"

Lisp的规则可以用一句话说:

一切都是(operator argument1 argument2 ...).永远如此。没有例外。

没有操作先例需要记忆,也没有特殊的语法。(+ 1 2)补充道。(if ...)决定。(define ...)名字。那些乍看之下令人望而生畏的括号,实际上是完全没有任何任意规则。

一周后,你就不再见到他们了。

定义与功能

#lang racket

(define pi-approx 3.14159)

(define (circle-area r)
  (* pi-approx r r))

(circle-area 2)   ; => 12.56636
  • define用名字创造一个常数。
  • define其中(name arguments...)创建一个函数。
  • 评论开头如下;.

匿名函数使用lambda(是的,那lambda Church 在 1930 年代的 lambda 演算是这一切的理论祖先):

(lambda (x) (* x x))          ; a function with no name
((lambda (x) (* x x)) 5)      ; => 25, applied directly

列表:Lisp的核心

Lisp 代表DSLtP罗斯辛。列表是基本结构:

(list 1 2 3)          ; => '(1 2 3)
'(1 2 3)              ; the same thing, "quoted"
(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》的亮点。将函数传递给其他函数是世界上最自然的事情:

(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次”,而是想“基础情况是什么,我该如何朝那个方向前进?”:

(define (factorial n)
  (if (= n 0)
      1
      (* n (factorial (- n 1)))))

(factorial 5)   ; => 120

为了让事情更具视觉效果,我们来画点东西。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,点击运行,然后看到Sierpinski三角形出现在你的屏幕上。

压轴:写代码的代码

记住引号'它把代码转化为数据。观看:

'(+ 1 2)          ; => the LIST (+ 1 2), not the number 3
(first '(+ 1 2))  ; => the symbol +
(eval '(+ 1 2))   ; => 3. You just evaluated data as code.

你的程序就是一份清单。你可以建立列表。因此:你可以用程序构建程序。这是同质性这也是Lisp 有 real 的原因宏量营养素不是像 C 语言那样的文本宏,而是在运行前接收代码和返回代码的函数。

Racket没有while循环?我们来发明一个:

(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中,语法由你决定。

艾伦·凯打电话给Lisp“麦克斯韦软件方程”:一个微小的核心,其他一切都可以由此推导出来。

接下来呢?

  • 如何设计程序——《Racket》设计的主题书籍,免费在线。
  • 《球拍指南》——官方文件,是市面上最好的之一。
  • 漂亮的球拍——学会构建你自己的语言。
  • SICP——如果你想了解完整的启蒙,那是经典中的经典。
添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论