On Lisp中文Common Lisp高级编程技术
On Lisp中文Common Lisp高级编程技术谨以此书南给我的家人和」 ackie。入译者序《 On Lisp》不是一本Lisp的入门教材,它更适合读过《 ANSI Common Lisp)或者《 Practical commonLisp》的Lisp学习者。它对Lisp宏本身及其使用做了非常全面的说明同时自底向上的编程思想贯穿全书这也是本书得名的原因即基于Lisp扩展Lisp。原作者 Paul graham同时也是《 ANSI Common Lisp》一书的作者。《 On Lisp》书早在1994年 ANSI Common Lisp标准发布以前书中使用了许多古老的Lisp操作符,其中一些代码已经无法在最新的 Common Lisp平台上执行了。所以译文里所有的源代码都被改成了符合现行 Common Lisp标准的瓶式凡译者修改过的地方都会以脚注的形式注明。我要特别感谢来自 AMD/AT的 Koy Chail同学他独立翻译了第5,6,22,23,25章及附录并对全书进行了细致的校对。另外 Kov Chai还主导了本书的均X排版工作。感谢 Yufei chen2同学提供改进排版的补丁。他还参与了第21章的翻译工作。Mathematical Systems,nc.的Lisp程序员」 anshi huang3同学是我最初翻译本书时的合作者他翻译了第24章并初步校对了本书前三章,Chun TIAN(binghe)4Netease. com. inc1tchaikov@gmail.com2cyfdecyfagmail.com3jianshihuangagmail.cominghe Lisp@gi前言本书适用于那些想更上一层楼的Lisp程序员。书中假设读者已经初步了解Lisp但不要求有丰富的编程经验。最初几章里会重温很多基础知识。我希望这些章节也会让有经验的Lisp程序员感兴趣因为它们以崭新的视角展示了熟知的主题通常很难一语道清门编程语言的精髓但 John Moderato的话已经很贴切了Lip是一门可编程的编程语言。( Lisp is a programmable programming language.)这难免以偏概全但这种让Lisp随心而变的能力在很大程度上正是Lisp专家和新手的不同之处。在自上而下把程序逐漸具伓化用编程语言实现设计的同时资深的凵is程序员也实践着自底冋上的方法,他们通过创建语言来描述程序的行为。本书教授自底向上编写程序的方法因为这是Lisp与生俱来的强项自底向上的设计( Bottom-up Design)随着软件复杂度的增长自底向上设计的重要性也日益提高。今天的程序可能不得不面对极其复杂甚至开放式的需求。在这种情况下传统的自上而下方法有时会失效。一种新的编程风格应运而生它和当前大部分计算机科学课程的思路截然不同:一个自底向上的程序由一系列的层写成每一层都作为更高一层的编程语言。 X Window和Tx就是这种程序设计风格的典范。本书有两层主题:首先对以自底向上的方法编制的程序来说Lisp语言是不二之选反过来編写Lisp程序的话采用自底向上的编程风格也是理所当然的。因此《 On Lisp》将吸引两类读者。对于那些有兴趣编写可扩展程序的人本书将告诉你如果有了合适的语言你能做些什么。对于Lisp程序员来说本书提供了第一手的实践指南指引他们把Lisp的优势发挥到极致。本书选用现在的这个书名是为了强调自底向上编程对于Lisp的重要性。你不再仅仅是用Lisp编写程序在L之上( On Lisp)你可以构造自己的语言然后再用这个语言来写程序。尽管用任何语言都可以写出自底向上风格的程序但Lisp对于这种编程风格来说是最自然的载体。在Lisρ里自底向上的设计并不是那种仅为少见的大型程序或者高难程序服务的专门技术。任何规模的程序都可以在一定程度上以这种方式编写。Lisp从一开始就被设计成可扩展的语言。这种语言本身基本上就是一个Lsp函数的集合这些函数和你自己定义的没有本质区别。更进一步Jisp函数可以表达成列表而列表同时也是Lisp的数据结构。这就意味着你可以写出能生成Lisp代码的Lisp函数个好的Lisp程序员必须懂得如何利用上述这种可能性。通常的途径是定义一种称为宏的操作符。驾驭宏是从编写正确的Lisp程序走向编写漂亮的程序过程中最重要的一步。入门级Lisp书籍给宏留下的篇幅仅限于一个宏的简短的概述:解释一下宏是什么加上几个例子蜻蜓点水地提一下说能用它实现一些奇妙的东西。不过本书会给予这些奇妙的东西特别的重视。这里的目标之一就是把所有关于宏的知识作次总结在以往人们只能从使用宏的经验和教训中来吸取这些知识。般来说Lisp的入门读物都不会强调Lisp和其他语言的区别这情有可原。它们必须想办法把知识传授给那些被教育成只会用 Pasca术语来构思程序的学生。如果非要细究这些区别的话只会把问题复杂化:例如 defun虽然看起来像一个过程定义但实际上它是一个编写程序的程序这个程序生成了一段代码而这段代码新建了一个函数对象然后用函数定义时给出的第一个参数作为这个函数对象的索引。本书的目的之一就是解释究竟是什么使Lisp不同于其他语言。刚落笔时我心里明白同等条件下自己会更倾向于用Lisp而不是C、 Pascal或 Fortran来写程序。我也知道这不只是个人好恶的问题。但当意识到就要郑重其事地告诉大家Lisp语言在某些方面更优秀时我发现应该做好准备說说到底为什么。曾有人问 Louis armstrong什么是爵士乐他答道“如果你问爵士乐是什么那你永远不会知道。"但他确实以一种方式回答了这个问题牠向世人展示了什么是爵士乐。同样也只有一种方式来解释Lisp的威力就是演示那些对于其他语言来说极其困难甚至不可能实现的技术。多数关于编程的书籍包括Lisp编程书籍采用的都是那些你可以用任何其它语言编写的程序。《 On Lisp》涉及的多是那些只能用Lisp写的程序。可扩展性自底向上程序设计交互式开发源代码转换嵌入式语言一这些都是Lisp展示其高级特性的舞台。当然从理论上讲狂意图灵等价的编程语言能做的事其它任何语言都可以做到。但这种能力和编程语言的能力却完全是两码事。理论上任何你能用编程语言做到的事也可以用图灵机来做但实际上在图灵机上编程得不偿失。所以当我说这本书是关于如何做那些其他语言力所不及的事情的时候我并非指数学意义上的“不可能″而是从编程语言的角度岀发的。这就是说如果你不得不用C来写本书中的一些程序你可能需要先用C写一个Lisp编译器。举个例子在C语言里嵌入 Prolog—你能想象这需要多少工作量吗?第24章将说明如何用180行Lisp做到这一点尽管我希望能比单单演示Lⅰsρ的强大之处做得更多。我也想解释为何Lisρ与众不同。这是一个更微妙的问题这个问题是那么难回答,它无法使用诸妇“符号计算”这样的术语来搪塞。我将尽我所学尽可能清楚明白地解释这些问题。本书规划由于函数是Lisp程序的基础所以本书开始的几章是有关函数的。第2章解释Lisp函数究竟是什么以及它们带来了何种可能。第3章讨论函数型编程的优点这是Lisp程序最主要的风格。第4章展示如何用函数来扩展Lisp。第5章建议了一种新的抽象方式即返回其他函数的函数。最后第6章显示了怎样使用函数来取代传统的数据结构。本书剩下的篇幅则更加关注宏。一部分原因是因为宏本身的內容就更多些一部分是因为至今尚无著作完整地介绍过宏的方方面面。第7-10章构成了一套关于宏技术的完整教程。学完这个教程后你将了解个有经验的Lisp程序员所知的关于宏的大多数内容:它们如何工作怎样定义测试以及调试它们河时应该使用以及何时不应该使用宏宏的主要类型怎样写生成宏展开代码的程序宏风格一般如何区别于Lisp风格以及怎样甄别和改正每一种宏特有的问题在这套宏教程之后,第11-18章展示了一些可以用宏来构造的强有力的抽象机制。第11章展示如何写典型的宏——那些创造上下文或者实现循环或条件判断的宏。第12章解释宏在操作普通变量中的角色。第13章展示宏如何通过将计算转移到编译期来使程序运行得更快。第14章介绍了指代( anaphoric)宏它允许你在程序里使用代词。第15章展示了宏如何为第5章里定义的函数生成器提供一个更便利的接口。第16章展示了如何使用定义宏的宏来让Lisp为你写程序。第17章讨论读取宏(read- macro)以及第18章解构宏第19章开始了本书的第四部分这一部分的重点是嵌入式语言。第19章通过展示同一个程序一个回答数据库查询的程序先是用解释器然后用真正的嵌入式语言来介绍这一主题。第20章展示了如何将续延( continuation)的概念引入 Common Lisp程序这是_种描述延续性计算的对象。续延是一个强有力的工具冋可以用来实现多进程和非确定性选择。至于如何把这些控制结构嵌入到凵isp中第21和22章将对此进一步展开讨论。非确定性听上去好像是一种具有非同寻常能力的抽象机制,它让你的程序似乎能未卜先知。第23和24章展示了两种嵌入式语言它们证明了非确定性绝非浪得虚名:一个完堊o的ATN解析器以及一个嵌入式 Prolog总共才200行代码。这些程序的长短本身并没有什么意义。如果你喜欢写像天书一样的程序没人知道你用200行代码能写出什么。关键在于这些程序并非靠编程技巧才变得短小而是由于它们是以Lisp所固有的自然的方式写成的。第23和24章的用意并不是教授如何用一页代码实现ATN解析器或者用两页实现 Prolog而是想说明这些程序当给出它们最自然的Lisp实现的时候是如此的简洁。后面这两个章节的嵌入式语言用实例证明了我开始时的两个观点:Lisp对于以自底向上的编程风格来说是一种自然的语言同时自底向上的编程风格也是编写Lisp程序理所当然的方式本书以关于面向对象编程的讨论做结其中特别讨论了 clos ,common isp对象系统。把这一主题留到最后我们可以更加清楚地看到面向对象的编程方式是一种扩展这种扩展植根于一些早已存在于Lisp的思想之上。它是多种可以建立在Ljsp上的抽象之一。自成一章的附注始于第269页。这些注释里包括参考文献补充或者替换的代码或者是有关Lisp但和当前主题没有直接联系的一些文字。注释是用页面留白上的小圆圈标注出来的就像这样。另外还有一。个关于包( package)的附录在第265页。去纽约逛一圈或许对世界上的多数文化会有走马观花的了解同样在把Lisp作为一门可扩展编程语言来学习也能接触到大部分的Lisp技术。这里描述的大多数技术通常都已为Lisp社区所熟知但很多内容至今也没有在任何地方有记载。而有些问题例如宏的作用或变量捕捉的本质甚至对于许多很有经验的Lisp程序员来说也只是一知半解。示例Lisp是个语言家族。由于 Common Lisp仍然是广泛使用的方言本书的大部分示例都是使用 CommonLisp编写的。在1984年 Guy steele的 Common Lisp: the Language(ct1)首次定义了这门语言。1990年该书第二版(ct|2)出版以后这一定义被取而代之,c2可能会让位于将来的ans标o准。本书包含数百个示例小到简单的表达式大至可运行的 Prolog实现。书中代码的编写尽量照顾到了各个细节使得它们可以在任何版本的 Common Lisp上运行。有极少数例子需要用到ct1规范之外的特性这些示例将会在正文中加以明确的标识。最后几个章节里包括了一些 Scheme的示例代码这些代码也会有淸楚的标记所有代码可以通过匿名FTP从 endor. harvard.edu下载在pub/ onlisp目录里。问题和评论可以发到 onlisp@das. harvard. edu致谢写此书时我要特别感谢 Robert morris的帮助。我经常去向他寻求建议每次都会满载而归。本书的些示例代码就来自他包括85页上的一个for版本,132页上的aand版本165页的 match211页的广度优先true- choose以及第24.2节的 Prolog解释器。事实上整本书都反映(有时基本是抄录)了过去七年来我跟 Robert之间的对话。(谢谢你rtm!)我还要特别感谢 David moon他仔细阅读了大部分手稿并且给出许多非常有用的评论。第12章是按照他的建议完全重写了的80页关于变量捕捉的示例代码也是他提供的。我很幸运地拥有 David Touretzky和 Koma brittain两位技术审槁人。有些章节就是在他们的建议下追加或者重写的。第277页给出的另一个非确定性选择操作符就出自 David Toureztky的一个建议。还有一些人欣然阅读了部分或全部手稿他们是 Tom Cheatham Richard draves(他在1985年也帮助重写了 a lambda和 propmacro) John Foderaro david Hendler george Luger robert muller,Mark Nitzberg以及 Guy steele我感谢 Cheatham教授以及整个哈佛他们为我提供了撰写此书的条件。也感谢Aieη实验室的全体成员包括 Tony Hartman Janusz Juda Harry bochner以及 Joanne Klys。Prentice hal的工作人员干得非常出色。我为与 Alan Apt这位优秀的编辑和好伙伴一起共事感到幸运。同时也感谢 Mona Pompili shirley Michaels以及 Shirley McGuire的组织工作和他们的幽默剑桥 Bow and arrow出版社的无与伦比的 Gino lee制作了封面。封面上的那棵树暗示了第18页上的观点。本书使用以排版这是一种由 Leslie Lamport在 Donald Knuth的TX基础上设计的语言另外使用了来自LA. Carr van Jacobson和 Guy Steele的宏。插图由 John Vlissides和 Scott stanton设计的 idraw完成。整本书用L. Peter deutsch的 Ghostscript生成之后在 Tim theisen的 Ghostview里预览。 Chiron inc.公司的 Gary Bisbee制作了能用来进行照相制版的拷贝我要感谢其他许多人包括 Paul Becker, Phil Chapnick Alice Hartley Glenn Hol| loway, MeichunHsu krzysztof Lenk arman maghbouleh Howard Mullings Nancy parmet robert Penny garySabot Patrick Slaney steve Strassman, Dave Watkins weickers一家还有 Bill woods。最后我要感谢我的父母谢谢他们为我树立的榜样还有对我的鼓励还有 Jackie要是我听得进他说的话,或许能学到点什么我希望阅读此书是件乐事。在所有我知道的语言中μLisp是我的最爱只因它是最优美的。本书着眼于最Lisp化的Lisp。写作这本书的过程充满了乐趣愿你在阅读此书时能感同身受,Paul graham
用户评论