while 循环与列表 ¶控制 while 循环的常用方式是判断列表是否还有元素。
有元素则继续循环,无元素则结束循环。
这是一项重要技术,我们用简短示例说明。
判断列表是否有元素的简单方法是直接对列表求值:
若无元素,即为空列表,返回 (),
等价于 nil(假)。
反之,包含元素的列表在求值时会返回这些元素。
由于 Emacs Lisp 将非 nil 的值均视为真,
因此非空列表在 while 中会被判定为真。
例如,你可以通过下面的 setq 表达式
将变量 empty-list 设为 nil:
(setq empty-list ())
执行该表达式后,你可以像平常一样对变量 empty-list 求值:
将光标放在符号后按下 C-x C-e,
回显区会显示 nil:
empty-list
反之,如果将变量设为包含元素的列表, 求值时就会显示该列表,执行下面两个表达式即可看到:
(setq animals '(gazelle giraffe lion tiger)) animals
因此,要创建一个判断列表 animals 是否有元素的
while 循环,循环开头可以这样写:
(while animals
...
当 while 判断第一个参数时,变量 animals 被求值,
返回一个列表。只要列表非空,while 就认为条件为真;
当列表为空时,则认为条件为假。
为避免 while 无限循环,
需要提供一种机制让列表最终变为空。
常用方法是在 while 表达式中使用某条语句
将列表设为自身的 CDR。
每次执行 cdr,列表都会变短,
直到最后只剩下空列表。
此时 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 的结合,
可以用来编写一个遍历列表并逐行打印每个元素的函数。