- 1、本文档共17页,可阅读全部内容。
- 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 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) ⾄少能得到我们想要的结果,并且免去了不必要的计
算
您可能关注的文档
- 笔记本win7 快捷键 你不知道用法 超炫.doc
- 笔记本玩游戏无法全屏显示最经典解决办法.doc
- 病毒包装实验整体流程和原理.doc
- 病毒入侵微机的途径及防治研究(计算机应用论文).doc
- 程序设计 课件第9篇.ppt
- 程与物理演示厅的示范.pdf
- 第 5 篇 函数作为返回值.pdf
- 第 6 篇 多人Git.pdf
- 第 19 篇 数据列表编程.pdf
- 第 22 篇 数据库.pdf
- 2025年高考数学圆锥曲线常用二级结论.docx
- 甘肃省靖远县高三下学期第二次联考数学(理)试题扫描版含答案.doc
- 四川省德阳五中高三二诊考试英语试卷扫描版含答案.doc
- 广东省高三第一次模拟考试英语试题扫描版含答案.doc
- 四川省德阳五中高三二诊考试数学(文)试卷扫描版含答案.doc
- 山西省高三第一次模拟考试理科综合试题扫描版含答案.doc
- 四川省广安眉山内江遂宁高三第三次诊断性考试理综化学试题扫描版含答案.doc
- 河南省六市高三下学期第一次联考试题(3月)数学(文)扫描版含答案.doc
- 山西省忻州市2017-2018学年高二上学期期末考试生物试题扫描版.doc
- 2025年国有企业领导班子、市行政审批和政务信息管理局党组书记、局长对照“四个带头”含违纪行为为典型案例检视剖析材料【2篇文】.docx
文档评论(0)