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