- 1、本文档共21页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
测系大修第7章宏
第 7 章 宏
第 7 章 宏
Lisp 中,宏的特性让你能⽤变换的⽅式定义操作符。宏定义在本质上,是能⽣成 Lisp
代码的函数 -- 个能写程序的程序。这 ⼩⼩开端引发了巨⼤的可能性,同时也伴随
着难以预料的风险。
第 7-10 章将带你⾛⼊宏的世界。本章会解释宏如何⼯作,介绍编写和调试它们的技
术,然后分析 些宏风格中存在的问题。
7.1 宏是如何⼯作的
由于我们可以调⽤宏并得到它的返回值,因此宏往往被⼈们和函数联系在 起。宏定
义有时和函数定义相似,⽽且不严谨地说,被⼈们称为 内置函数 的 do 其实就是
个宏。但如果把两者过于混为 谈,就会造成很多困惑。宏和常规函数的⼯作⽅式截
然不同,并且只有知道宏为何不同,以及怎样不同, 才是⽤好它们的关键。 个函数
只产⽣结果,⽽宏却产⽣表达式。当它被求值时,才会产⽣结果。
要⼊门,最好的办法就是直接看个例⼦。假设我们想要写 个宏 nil!,它把实参设
置为 nil。让(nil! x) 和 (setq x nil) 的效果 样。我们完成这个功能的⽅法
是:把 nil! 定义成宏,让它来把前 种形式的实例变成后 种形式的实例:
(defmacro nil! (var)
(list setq var nil))
NIL!
⽤汉语转述的话,这个定义相当于告诉 Lisp : ⽆论何时,只要看到形如 (nil!) 的
表达式,请在求值之前先把它转化成 (setq nil) 的形式。
宏产⽣的表达式将在调⽤宏的位置求值。宏调⽤是 个列表,列表的第 个元素是宏
的名称。当我们把宏调⽤ (nil! x) 输⼊到 toplevel 的时候发⽣了什么? Lisp ⾸先
会发觉 nil! 是个宏的名字,然后:
1. 按照上述定义的要求构造表达式,接着,
2. 在调⽤宏的地⽅求值该表达式。
构造新表达式的那 步被称为宏展开 (macro expansion )。Lisp 查找 nil! 的定义,
其定义展⽰了如何为宏调⽤构建 个即将取代它的表达式。和函数 样,nil! 的定
义也应⽤到了宏调⽤传给它的表达式参数上。
它返回 个三元素列表,这三个元素分别是: setq、作为参数传递给宏的那个表达
式,以及 nil。在本例中,nil! 的参数是 x ,宏展开式是 (setq x nil)。
宏展开之后是第⼆步:求值 (evaluation )。Lisp 求值宏展开式 (setq x nil) 时就
好像是你原本就写在那⼉的 样。求值并不总是⽴即发⽣在展开之后,不过
在 toplevel 下的确是这样的。 个发⽣在函数定义⾥的宏调⽤将在函数编译时展
开,但展开式 或者说它产⽣的对象代码, 要等到函数被调⽤时才会求值。
如果把宏的展开和求值分清楚,你遇到的和宏有关的困难,或许有很多就能避免。当
编写宏的时候,要清楚哪些操作是在宏展开期进⾏的,⽽哪些操作是在求值期进⾏
的,通常,这两步操作的对象截然不同。宏展开步骤处理的是表达式,⽽求值步骤处
理的则是它们的值。
有些宏的展开过程⽐ nil! 的情况更复杂。nil! 的展开式只是调⽤了 下内置
的 special form,但往往 个宏的展开式可能会是另 个宏调⽤,就好像是 层
套 层的俄罗斯套娃。在这种情况下,宏展开就会继续抽丝剥茧直到获得 个没有宏
的表达式。这 步骤中可以经过任意多次的展开操作, 直到最终停下来。
尽管有许多语⾔也提供了某种形式的宏,但 Lisp 宏却格外强⼤。在编译 Lisp ⽂件
时,解析器先读取源代码,然后将其输出送给编译器。这⾥有个天才的⼿笔:解析器
的输出由 Lisp 对象的列表组成。通过使⽤宏,我们可以操作这种处于解析器和编译器
之间的中间状态的程序。如果必要的话,这些操作可以⽆所不包。 个⽣成展开式的
宏拥有 Lisp 的全部威⼒,可任其驱驰。事实上,宏是货真价实的 Lisp 函数 那种能返
回表达式的函数。虽然 nil! 的定义中只是调⽤了 下 list ,但其他宏⾥可能会驱
动整个⼦程序来⽣成其展开式。
有能⼒改变编译器所看到的东西,差不多等同于能够对代码进⾏重写。所以我们就可
以为语⾔增加任何构造,只要⽤变换的⽅法把它定义成已有的构造。
7.2 反引⽤ (backquote )
反引⽤ (backquote )是引⽤ (quote )的特别版本,它可以⽤来创建 Lisp 表达式的模
板。反引⽤最常见的⽤途之 是⽤在宏定义⾥。
反引⽤
您可能关注的文档
- 精品社保基础知识.doc
- 精品神奇的极光.doc
- 精品神经外科手术麻醉.ppt
- 浅析离子交换与吸附.pdf
- 精品离子反应总复习.ppt
- 方程式正误判断.ppt
- 精品离子浓度大小的比较.ppt
- 精品科学:5.1《物体的内能》课件2(华师大版九上).ppt
- 前台人员着装规范.ppt
- 硬盘删除的文件如何恢复.ppt
- 2025年包头轻工职业技术学院单招职业适应性测试题库(全优).docx
- 2025年乐山职业技术学院单招职业倾向性测试题库带答案(新).docx
- 2025年吉林司法警官职业学院单招职业适应性测试题库含答案ab卷.docx
- 2025年亳州职业技术学院单招职业技能测试题库含答案(基础题).docx
- 2025年临夏现代职业学院单招职业技能测试题库(有一套).docx
- 2025年随州职业技术学院单招语文测试模拟题库附答案.docx
- 2025年九江理工职业学院单招职业适应性测试题库及答案(各地真题).docx
- 2024秋季开学第一课防疫情教案最新.pptx
- 2025年吉林水利电力职业学院单招职业倾向性测试题库有答案.docx
- 2024第二届中国上海商用密码展暨高峰论坛.pptx
文档评论(0)