Looping(循环)
循环结构是另外一类主要的控制结构。Common Lisp 的循环机制,除了更加强大和灵活以外,还是一门关于宏所提供的 “鱼和熊掌兼得” 的编程风格的有趣课程。
初看起来,Lisp 的 25 个特殊操作符中没有一个能够直接支持结构化循环,所有的 Lisp 循环控制构造都是构建在一对提供原生 goto
机制的特殊操作符之上的宏。和许多好的抽象或句法等一样,Lisp 的循环宏构建在以那两个特殊操作符为基础的一组分层抽象之上。
最底层(不考虑特殊操作符)是一个非常通用的循环构造 DO。尽管非常强大,但 DO 和许多其他的通用抽象一样,在应用于简单情形时显得过于复杂。因此 Lisp 还提供了另外两个宏,DOLIST 和 DOTIMES。它们不像 DO 那样灵活,但却提供了对于常见的在列表元素上循环和计数循环的便利支持。尽管一个实现可以用任何方式来实现这些宏,但它们被典型实现为展开到等价 DO 循环的宏。因此,在由 Common Lisp 特殊操作符所提供的底层原语之上,DO 提供了一种基本的结构化循环构造,而 DOLIST 和 DOTIMES 则提供了两种易用却不那么通用的构造。并且如同在下一章将看到的那样,对于那些 DOLIST 和 DOTIMES 无法满足需要的情形,还可以在 DO 之上构建自定义的循环构造。
最后,LOOP 宏提供了一种成熟的微型语言,它用一种非 Lisp 的类似英语(或至少类似 Algol)的语言来表达循环构造。一些 Lisp 黑客热爱 LOOP,其他人则讨厌它。LOOP 爱好者们喜欢它是因为它用了一种简洁的方式来表达特定的常用循环构造。而贬低者们不喜欢它则是因为它不太像 Lisp。但无论你倾向于哪一方,LOOP 本身都是一个为语言增加新构造的宏展示其强大威力的突出示例。