dolist
宏例如,假设您想反转一个列表,使得“first” “second” “third” 变成 “third” “second” “first”。
实际上,您可以使用 reverse
函数,如下所示:
(setq animals '(gazelle giraffe lion tiger)) (reverse animals)
以下是使用 while
循环反转列表的方法:
(setq animals '(gazelle giraffe lion tiger)) (defun reverse-list-with-while (list) "使用while循环反转LIST的顺序。" (let (value) ; 确保列表从空开始 (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) "使用dolist宏反转LIST的顺序。" (let (value) ; 确保列表从空开始 (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 一个while
循环和一个列表)。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
中返回。