网站大量收购闲置独家精品文档,联系QQ:2885784924

第 4 篇 实用函数.pdf

  1. 1、本文档共17页,可阅读全部内容。
  2. 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
第 4 章 实⽤函数 第 4 章 实⽤函数 Common Lisp 操作符分为三类:可⾃定义的函数和宏,以及不能⾃定义的特殊形式 (specialform )。本章 讲述⽤函数来扩展 Lisp 的技术。但这⾥的 技术 和通常的含 义不太⼀样。关于这些函数,重要的不是知道怎样写,⽽是要知道它们从何⽽来。编 写 Lisp 扩展所使⽤的技术和你编写其他任何 Lisp 函数所使⽤的技术⼤同⼩异。编写 Lisp 扩展的难点并不在于代码怎么写,⽽在于决定写什么。 4.1 实⽤⼯具的诞⽣ ⾃底向上程序设计,简单说,就是程序员满腹牢骚,到底是谁把我的 Lisp 设计成这 个模样。你⼀边在编写程序,同时也在为 Lisp 增加那些可以让你程序更容易编写的 新操作符。这些新操作符被称为实⽤⼯具。 实⽤⼯具 这⼀术语并⽆明确的定义。有那么⼀段代码,如果把它看成独⽴的程序, 感觉⼩了点,要是把它作为特定程序的⼀部分的话,这段代码又太通⽤了,这时就可 以称之为实⽤⼯具。举例来说,数据库不能称为实⽤⼯具,但是对列表进⾏单⼀操作 的函数就可以。⼤多数实⽤⼯具和 Lisp 已有的函数和宏很相似。事实上,许多 Common Lisp 内置的操作符就源⾃实⽤⼯具。⽤于收集列表中所有满⾜条件元素的 remove-if-not 函数,在它成为 Common Lisp 的⼀部分以前,就被程序员们私下⾥各⾃ 定义了多年。 学习编写实⽤⼯具与其说是学习编写的技术,不如说是养成编写实⽤⼯具的习惯。⾃ 底向上程序设计意味着在编写程序的同时,也在设计⼀门编程语⾔。为了做好这⼀ 点,你必须培养出⼀种能看出程序中缺少何种操作符的洞察⼒。你必须能够在看到⼀ 个程序时说, 啊,其实你真正的意思是这个。 举个例⼦,假设 nicknames 是这样⼀个函数, 它接受⼀个名字,然后构造出⼀个列 表,列表由这个名字的所有昵称组成。有了这个函数,我们怎样收集⼀个名字列表对 应的所有昵称呢? Lisp 的初学者可能会写出类似的函数: (defun all-nicknames (names) (if (null names) nil (nconc (nicknames (car names)) (all-nicknames (cdr names))))) ⽽更有经验的 Lisp 程序员可能⼀看到这样的函数就会说 啊,其实你真正想要的是 mapcan。 然后,不再被迫定义并调⽤⼀个新函数来找出⼀组⼈的所有昵称,现在只 要⼀个表达式就够了: (mapcan #nicknames people) 定义 all-nicknames 完全是在重复地发明轮⼦。它的问题还不只于此: 它同时也葬送了 ⼀个机会: 本可以⽤通⽤操作符来直接完成某件事,却使⽤了专⽤的函数来实现它。 对这个例⼦来说,操作符 mapcan 是现成的。任何知道 mapcan 的⼈在看到 all- nicknames 时都会觉得有点不太舒服。要想在⾃底向上程序设计⽅⾯做得好,就要在 缺少的操作符还没有写出来的时候,同样觉得不舒服。你必须能够在说出 你真正想 要的是 x 的同时,知道 x 应该是什么。 Lisp 编程的要求之⼀,就是⼀旦有需要,就应该构思出新的实⽤⼯具。本章的⽬的就 是揭⽰这些⼯具是如何从⽆到有的。假设 towns 是⼀个附近城镇的列表,按从近到远排 序,bookshops 函数返回⼀个城市中所有书店的列表。如果想要查找最近的⼀个有书 店的城市,以及该城市⾥的书店,我们可能⼀开始会这样做: (let ((town (find-if #bookshops towns))) (values town (bookshops town))) 但是这样有点不⼤合适: 当 find-if 找到⼀个 bookshops ,返回⾮空元素时, 这个值被 直接丢掉了,然后马上又要重新算⼀次。如果 bookshops 是⼀个耗时的函数调⽤, 那 么这个⽤法 是既丑陋又低效的。为了避免做⽆⽤功,我们⽤下⾯的函数代替它: (defun find-books (towns) (if (null towns) nil (let ((shops (bookshops (car towns)))) (if shops (values (car towns) shops) (find-books (cdr towns)))))) 这样,调⽤ (find-books towns) ⾄少能得到我们想要的结果,并且免去了不必要的计 算

文档评论(0)

kehan123 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档