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 中返回。