dolist 宏 ¶例如,假设你想反转一个列表, 让 “第一个” “第二个” “第三个” 变为 “第三个” “第二个” “第一个”。
实际使用中,你会直接用 reverse 函数,如下:
(setq animals '(gazelle giraffe lion tiger)) (reverse animals)
下面是用 while 循环实现列表反转的方式:
(setq animals '(gazelle giraffe lion tiger))
(defun reverse-list-with-while (list)
"Using while, reverse the order of LIST."
(let (value) ; make sure list starts empty
(while list
(setq value (cons (car list) value))
(setq list (cdr list)))
value))
(reverse-list-with-while animals)
下面是使用 dolist 宏的写法:
(setq animals '(gazelle giraffe lion tiger))
(defun reverse-list-with-dolist (list)
"Using dolist, reverse the order of LIST."
(let (value) ; make sure list starts empty
(dolist (element list value)
(setq value (cons element value)))))
(reverse-list-with-dolist animals)
在 Info 中,你可以将光标放在每个表达式的右括号后, 输入 C-x C-e;每种情况都应在回显区看到:
(tiger lion giraffe gazelle)
对于本例,显然已有的 reverse 函数是最佳选择。
while 循环和我们第一个示例类似(see A while Loop and a List)。
while 首先检查列表是否有元素;
如果有,就通过将列表第一个元素添加到现有列表(循环第一次迭代时为 nil)
来构造新列表。由于第二个元素被追加到第一个元素前面,
第三个被追加到第二个前面,列表就被反转了。
在使用 while 循环的表达式中,
(setq list (cdr list)) 会缩短列表,
使 while 循环最终停止。
同时,它在每次循环中创建一个更短的新列表,
为 cons 表达式提供新的第一个元素。
dolist 表达式的作用与 while 非常相似,
区别在于 dolist 宏自动完成了编写 while 时需要手动做的部分工作。
和 while 循环一样,dolist 会进行循环。
不同之处在于,它每次循环都会自动缩短列表 —
自行取列表 CDR — 并自动将每个更短列表的 CAR
绑定到它的第一个参数。
在示例中,每个更短列表的 CAR 用符号 ‘element’ 表示,
列表本身叫作 ‘list’,返回值叫作 ‘value’。
dolist 表达式的其余部分是循环体。
dolist 表达式将每个更短列表的 CAR 绑定到 element,
然后执行表达式体,并重复循环。
结果由 value 返回。