while
循环和列表控制 while
循环的常见方法是测试列表是否包含任何元素。如果包含元素,则循环将继续;但如果不包含元素,则循环结束。由于这是一种重要的技术,我们将创建一个简短的示例来说明它。
测试列表是否包含元素的一种简单方法是评估列表:如果没有元素,它是一个空列表,将返回空列表 ()
,这是 nil
或 false 的同义词。另一方面,具有元素的列表在评估时将返回这些元素。由于Emacs Lisp认为任何非 nil
的值都为真,因此返回元素的列表在 while
循环中将测试为真。
例如,您可以通过评估以下 setq
表达式将变量 empty-list
设置为 nil
:
(setq empty-list ())
在评估了 setq
表达式之后,您可以以通常的方式评估变量 empty-list
,即将光标放在符号后面,然后键入 C-x C-e;在您的回显区域中将显示 nil
:
empty-list
另一方面,如果将变量设置为具有元素的列表,则在评估变量时将显示该列表,如通过评估以下两个表达式所示:
(setq animals '(gazelle giraffe lion tiger)) animals
因此,要创建一个 while
循环,测试列表 animals
中是否有任何项,循环的第一部分将被编写为:
(while animals …
当 while
测试其第一个参数时,变量 animals
被评估。它返回一个列表。只要列表具有元素,while
将认为测试的结果为真;但当列表为空时,它将认为测试的结果为假。
为防止 while
循环无限运行,需要提供某种机制以最终清空列表。一个常用的技术是在 while
表达式的后续形式中之一将列表的值设置为列表的 CDR。每次评估 cdr
函数时,列表都会变得更短,直到最终只剩下空列表。此时,while
循环的测试将返回假,while
的参数将不再被评估。
例如,将绑定到变量 animals
的动物列表可以通过以下表达式设置为原始列表的 CDR:
(setq animals (cdr animals))
如果您已经评估了前面的表达式,然后评估此表达式,您将在回显区域中看到 (giraffe lion tiger)
。如果再次评估表达式,将显示 (lion tiger)
。如果再次评估它,(tiger)
将出现,然后是空列表,由 nil
表示。
使用 cdr
反复使真或假测试最终测试为假的 while
循环的模板如下:
(while test-whether-list-is-empty body… set-list-to-cdr-of-list)
这个测试和使用 cdr
的功能可以放在一起,形成一个函数,该函数遍历列表并在各自的行上打印列表的每个元素。