- 4
- 0
- 约1.09万字
- 约 9页
- 2017-05-28 发布于江苏
- 举报
第 8 章 何时使用宏
第 8 章 何时使⽤宏
第 8 章 何时使⽤宏
我们如何知道⼀个给定的函数是否真的应该是函数,⽽不是宏呢?多数时候,会很容
易 清楚在哪种情况下需要⽤到宏,哪种情况不需要。缺省情况下,我们应该⽤函
数,因为如果函数能解决问题,⽽偏要⽤上宏的话,会让程序变得不优雅。我们应当
只有在宏能带来特别的好处时才使⽤它们。
什么情况下,宏能给我们带来优势呢?这就是本章的主题。通常这不是锦上添花,⽽
是⼀种必须。⼤多数我们⽤宏可以做到的事情,函数都⽆法完成。第 8.1 节列出了只
能⽤宏来实现的⼏种操作符。尽管如此,也有⼀⼩类 (但很有意思的) 情况介于两者
之间,对它们来说,不管把操作符实现成函数还是宏似乎都⾔之有理。对于这种情
况,第 8.2 节给出了关于宏的正反两⽅⾯考量。最后,在充 考察了宏的能⼒后,我
们在第 8.3 节⾥转向⼀个相关问题:⼈们都⽤宏⼲什么?
8.1 当别⽆他法时
优秀设计的⼀个通⽤原则就是:当你发现在程序中的⼏处都出现了相似的代码时,就
应该写⼀个⼦例程,并把那些相似的语句换成对这个⼦例程的调⽤。如果也把这条原
则⽤到 Lisp 程序上,就必须先决定这个 ⼦例程 应该是函数还是宏。
有时,可以很容易确定应当写⼀个宏⽽不是函数,因为只有宏才能满⾜需求。⼀个像
1+ 这样的函数或许既可以写成函数也可以写成宏:
(defun 1+ (x) (+ 1 x))
(defmacro 1+ (x) (+ 1 ,x))
但是来⾃第 7 .3 节的 while ,则只能被定义成宏:
(defmacro while (test body body)
(do ()
((not ,test))
,@body))
⽆法⽤函数来重现这个宏的⾏为。while 的定义⾥拼接了⼀个作为 body 传⼊ do 的
主体⾥的表达式,它只有当 test 表达式返回 nil 时才会被求值。没有函数可以做到
这⼀点;是因为在函数调⽤⾥,所有的参数在函数调⽤开始之前就会被求值。
当你需要⽤宏时,你看中了它哪⼀点呢?宏有两点是函数⽆法做到的:宏可以控制
(或阻⽌) 对其参数的求值,并且它可以展开进⼊到主调⽅的上下⽂中。任何需要宏
的应⽤,归根到底都是要⽤上述两个属性中的⾄少⼀个。
宏不对其参数进⾏求值 ,这个⾮正式的说法不太准确。更确切的说法应该是,宏能
控制宏调⽤中参数的求值。取决于参数在宏展开式中的位置,它们可以被求值⼀
次,多次,或者根本不求值。宏的这种控制主要体现在四个⽅⾯:
1. 变换
Common Lisp 的 setf 宏就是这类宏中的⼀员,它们在求值前都会对传⼊的参数严加检
查。内置的访问函数 (access function ) 通常都有⼀个对应的逆操作,其作⽤是对该
访问函数所获取的对象赋值。car 的逆操作是 rplaca ,对于 cdr 来说是 rplacd ,等等。
有了 setf ,我们就可以把对这些访问函数的调⽤当成变量赋值。(setf (car x)
a) 就是个例⼦,这个表达式可以展开成 (progn (rplaca x a) a).
为了有这样的效果,setf 必须⾮常了解它的第⼀个参数。如果要知道上述的情况需要
⽤到 rplaca ,
setf 就得清楚它的第⼀个参数是个以 car 开始的表达式。这样的话,setf 以及其他修
改参数的操作符,就必须被写成宏。
2. 绑定
词法变量必须在源代码中直接出现。例如,由于 setq 的第⼀个参数是不求值的,所
以,所有在setq 之上构建的东西都必须是展开到setq 的宏,⽽不能是调⽤它的函数。
对于 let 这样的操作符也是如此,它的实参必须作为 lambda 表达式的形参出现,还有
类似 do 这样展开到 let 的宏也是这样,等等。任何新操作符,只要它修改了参数的词
法绑定,那么它就必须写成宏。
3. 条件求值
函数的所有参数都会被求值。在像 when 这样的结构⾥,我们希望⼀些参数仅在特定
条件下才被求值。只有通过宏才可能获得这种灵活性。
4. 多重求值
函数的所有参数不但都会被求值,⽽且求值的次数都正好是⼀次。我们需要⽤宏来定
义像 do 这样的结构,这样⼦,就可以对特定的参数多次求值。
也有⼏种⽅式可以利⽤宏产⽣的内联展开式带来的优势。这⾥必须强调⼀点,宏展开
后⽣成的展开式将会出现在宏调⽤所在的词法环境之中,因为下列三种⽤法有两种都
基于这个事实。它们是:
5. 利⽤调⽤⽅环境
宏⽣成的展开式可以含有这样的变量,变量的绑
您可能关注的文档
- 环境史视野下近现代云南城市化初探.pdf
- 环境污染加剧石质文物风化_机理_过程及防护措施_周文静.pdf
- 现代化进程的节点与政治转型.PDF
- 现场挑选健康的垂耳兔不难,行家传授5个技巧.pdf
- 现货涨势延续期价高位调整.PDF
- 理性化、市场转型与就业机会差异 中国城镇居民工作获得的历时性分析(1949—2003)_694603939.pdf
- 瑜伽妈妈给瑜伽宝宝的话,好温馨,好感动!.pdf
- 瓦尔特·本雅明论广播.PDF
- 生产的规.PDF
- 生活是自己的!装修的细节不能让步!99%网友后悔看这文章太晚!.pdf
- 小区绿化施工协议书.docx
- 墙面施工协议书.docx
- 1 古诗二首(课件)--2025-2026学年统编版语文二年级下册.pptx
- (2026春新版)部编版八年级道德与法治下册《3.1《公民基本权利》PPT课件.pptx
- (2026春新版)部编版八年级道德与法治下册《4.3《依法履行义务》PPT课件.pptx
- (2026春新版)部编版八年级道德与法治下册《6.2《按劳分配为主体、多种分配方式并存》PPT课件.pptx
- (2026春新版)部编版八年级道德与法治下册《6.1《公有制为主体、多种所有制经济共同发展》PPT课件.pptx
- 初三教学管理交流发言稿.docx
- 小学生课外阅读总结.docx
- 餐饮门店夜经济运营的社会责任报告(夜间贡献)撰写流程试题库及答案.doc
最近下载
- SJ∕T 10460-2016 太阳光伏能源系统图用图形符号.pdf
- 新求精德语强化教程(第4版)初级1课后练习答案(改进版) .pdf VIP
- 北师大版三年级下册数学全册教学设计(配2026年春改版教材).docx
- (2026年)跌倒坠床护理综合指南PPT课件.pptx VIP
- 工程设计应急响应方案(3篇).docx VIP
- 征信简版电子版PDF个人信用报告最新版2024年可编辑带水印模板.pdf VIP
- ntvf调试资料解读.doc VIP
- 电影《色.戒》的叙事伦理.doc VIP
- 上海大学2023-2024学年第1学期《高等数学(上)》期末考试试卷(A卷)附参考答案.pdf
- 佳能EOS1500D基本使用说明书说明书.pdf VIP
原创力文档

文档评论(0)