logo资料库

Programming Language: Application and Interpretation 中文版.pdf

第1页 / 共208页
第2页 / 共208页
第3页 / 共208页
第4页 / 共208页
第5页 / 共208页
第6页 / 共208页
第7页 / 共208页
第8页 / 共208页
资料共208页,剩余部分请下载后查看
封面
1. 引言
2. 本书有关语法解析的一切
3. 解释器初窥
4. 初试去语法糖
5. 添加函数
6. 从替换模型到环境模型
7. 任意位置的函数
8. 可变结构体和变量
9. 递归和循环:子程序与数据
10. 对象
11. 内存管理
12. 表示层抉择
13. 语言中支持去语法糖
14. 控制指令
15. 静态地检查程序中的不变量:类型
16. 动态地检查程序中的不变量:契约
17. 其他调用语义
目錄 封面 1. 引言 2. 本书有关语法解析的一切 3. 解释器初窥 4. 初试去语法糖 5. 添加函数 6. 从替换模型到环境模型 7. 任意位置的函数 8. 可变结构体和变量 9. 递归和循环:子程序与数据 10. 对象 11. 内存管理 12. 表示层抉择 13. 语言中支持去语法糖 14. 控制指令 15. 静态地检查程序中的不变量:类型 16. 动态地检查程序中的不变量:契约 17. 其他调用语义 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18 2
封面 PLAI-cn 来源:lotuc/PLAI-cn 翻译准侧 1. 尽可能忠于原文(总原则) 2. 代码中\全部保留,在同一行最后分号注释加上中文翻译,比如 ::= ;返回值类型,第一次尝试 3. 术语翻译,可以在第一次出现/定义的地方后附括号,括号内标注英文,比如 闭包 (Closure) 4. Excise和Think now统一翻译成练习和思考题 5. 注释也请翻译,根据实际情况,直接放在文中相应位置,或者放在本节最后处 6. 代码中出现的英文字符串,也在同一行后加中文注释,比如 (error 'num+ "one argument was not a number") ;有一个参数不是数字 7. md中代码一律使用Racket标记(不使用scheme,会导致中括号显示出问题) 8. 英文原文的斜体和粗体字,统一对应为中文的粗体字 PLAI 第二版 Gitbook - PLAI-cn zhihu - lotuc 1. The translation has not been checked by the original author 2. The correct, definitive version is at the original link. 3
封面 译者 lotuc MrMathematica 4
1. 引言 1 引言 1.1 我们的哲学 请参见Youtube视频。 1.2 本书的结构 与某些教科书不同,本书并没有采取自上而下的叙述方式,而是采用了对话发展的方式,有 时也会回头描述讲过的话题。如同现实中的程序员,我们通常一步一步来构造程序。有时候 我们的程序也会包括错误,这并不是因为我不知道该怎么写出正确的程序,而是因为这是帮 助你学习的最好方式。错误会迫使你没法被动的学习,而是必须钻研:你永远也没法确信读 到的材料就是真实的。 最终,你会得到正确的答案。短期来说,这种方式使人挫折,而且读者也没法将本书当做参 考书来使用(你没法打开书,翻到随便一页,就认为其中的内容是正确的)。但是,挫败感 是学习的一个部分。我不觉得有好方法绕开它。 在书中你会遇到 练习 这是练习。请做题。 这和传统教材中的练习题一样,需要你独立完成。如果你确实在某个课程中使用本教材,有 可能这就是课后作业。但是本书也包含这种: 思考题 这是思考题,你看到了吗? 当你看到思考题的时候,请停下来。阅读、思考,形成答案之后再继续。这是因为思考题本 质上就是练习题,唯一的区别是后文会给出其答案,或者你可以通过运行程序自行得到答 案。如果你不加思考的继续阅读,那么你就会读到答案(或者,如果答案是可以通过运行程 序获得的情况下,完全忽略答案)。这样做既没有测试你的知识水平,也无法锻炼你的思维 能力。换一种说法,思考题是鼓励你积极学习的一部分。 1.3 本书使用的语言 5
1. 引言 本书使用的主要语言是Racket。然而,跟很多操作系统一样,Racket支持很多编程语言,所 以你必须显式的告诉Racket你在使用什么语言进行编程。在Unix系统的shell脚本中你需要在 脚本开头添加如下一行来指明语言: #!/bin/sh 在脚本的头部,你可能会类似的指定: 类似的,Racket需要你声明所使用的语言。Racket语言可能使用和Racket一样的括号语法, 但是有不同的语义;或语义相同语法不同;或者有不同的语法和语义。因此每个Racket 程序 以 #lang <语言名字> 开头。默认的语言为Racket(名字为racket)。【注释】这本书中我们几 乎总是使用语言: plai-typed 在DrRacket版本5.3中,打开“语言/Language”菜单,“选择语言/Choose Language”菜单 项,然后选择“使用代码中指定的语言/Use the language declared in the source”。 使用该语言时,除非特别指明,请在程序的第一行添加(本书后面例子代码中请假定我们添 加了该行): #lang plai-typed Typed PLAI语言和传统Racket最主要的不同是它是静态类型的。它还给你提供了些有用的的 东西(construct): define-type 、 type-case 和 test 。【注释】下面是它们的使用实例。 创建新的数据类型: 它还提供了其他一些有用的命令,比如控制测试输出的命令等。请参考该语言的文档了 解。在DrRacket版本5.3中,打开“帮助/Help”菜单,选择“帮助台/Help Desk”菜单项,然 后在帮助台的搜索栏中输入“plai-typed”。 (define-type MisspelledAnimal [caml (humps : number)] [yacc (height : number)]) 它做的事情类似于在Java中:创建抽象类 MisspelledAnimal ,它有两个实体子 类: caml 和 yacc ,它们的构造参数分别为 humps 和 height 。 该语言中,我们通过下面方式创建实例: 6
1. 引言 (caml 2) (yacc 1.9) 如同其名字暗示的, define-type 会创建给定名字的数据类型。当我们把该数据类型的值绑定 到变量时就需要用到其类型: (define ma1 : MisspelledAnimal (caml 2)) (define ma2 : MisspelledAnimal (yacc 1.9)) 事实上这里你并不需要显式的声明类型,因为Typed PLAI在很多情况下(包括这里)都能够 推断出正确的数据类型。因此上面的代码可以写成: (define ma1 (caml 2)) (define ma2 (yacc 1.9)) 不过我们倾向于对类型进行显式的声明。这么做一方面是尊崇规则,另一方面当我们日后阅 读代码时有助于理解。 类型的名字可以递归的使用,本书会经常使用这种方式(例如2.4节中)。 该语言为我们提供了模式匹配功能,例如这个函数体: (define (good? [ma : MisspelledAnimal]) : boolean (type-case MisspelledAnimal ma [caml (humps) (>= humps 2)] [yacc (height) (> height 2.1)])) 在表达式 (>= humps 2) 中, humps 被绑定为 caml 实例的构造时所用到的参数。 最后,你应该编写测试案例,理想情况下,应该在开始定义函数之前写。当然在定义函数之 后也需要写,以防代码被意外修改。 (test (good? ma1) #t) (test (good? ma2) #f) 当你运行上面的代码时,语言会告诉你两个测试都通过了。要了解更多请参阅文档。 这里有一点可能比较费解。在模式匹配中,匹配数据字段时我们使用了和数据定义时相同的 名字, humps (和 height )。这是完全没有必要的,模式匹配是基于位置的而不是名字。 因此我们完全可以使用其它名字: (define (good? [ma : MisspelledAnimal]) : boolean (type-case MisspelledAnimal ma [caml (h) (>= h 2)] [yacc (h) (> h 2.1)])) 7
1. 引言 因为每个h仅在其被引入的匹配分支中可见,所以上面的代码没有重名的问题。命名是请尊崇 传统和可读性。通常来说,定义数据类型时可以使用长而描述性的名字;而定义类型子句时 请使用简短的名字,因为日后这些名字会不断被用到。 我觉得很少有需要你会用到类型判断函数(如caml?),不过你可以用。数据类型定义时还会 生成字段提取函数,例如 caml-humps 。有时候,直接使用字段提取函数会比使用模式匹配更 简单。当然一般来说还是模式匹配更好用,就如刚才的 good? 所示。不过为了完整,我们实 现如下: (define (good? [ma : MisspelledAnimal]) : boolean (cond [(caml? ma) (>= caml-humps ma) 2] [(yacc? ma) (> (yacc-height ma) 2.1)])) 思考题 如果给函数传入了错误的数据类型会发生什么?比如传给caml构造器一个字符串?或者 传给前述两个版本的 good? 函数一个数? 8
分享到:
收藏