迭代是指重复执行程序的某一部分。例如,你可能想对列表中的每个元素执行一次计算,或者对从 0 到 n 的每个整数各执行一次。在 Emacs Lisp 中,可以使用特殊形式 while 来实现:
while 首先对 condition(条件)求值。如果结果为非 nil,则按文本顺序依次执行 forms(语句体)。然后它会再次对条件求值,如果结果仍为非 nil,则再次执行语句体。这一过程会不断重复,直到 condition 求值结果为 nil。
迭代次数没有限制。循环会一直执行,直到条件求值为 nil,或者发生错误、或通过 throw 跳出循环为止(see 非局部退出)。
while 形式的返回值永远是 nil。
(setq num 0)
⇒ 0
(while (< num 4)
(princ (format "Iteration %d." num))
(setq num (1+ num)))
⊣ Iteration 0.
⊣ Iteration 1.
⊣ Iteration 2.
⊣ Iteration 3.
⇒ nil
要编写先执行循环体、后判断条件的 repeat-until 循环,可以将循环体 + 结束判断放在一个 progn 里,并作为 while 的第一个参数,如下所示:
(while (progn
(forward-line 1)
(not (looking-at "^$"))))
该代码会向下移动一行,并持续按行移动,直到抵达空行。这段代码的特殊之处在于:while 没有独立的循环体,仅包含结束判断(而该判断同时完成了移动光标(point)的实际操作)。
dolist 和 dotimes 宏为两种常见循环类型提供了简洁的实现方式。
该结构会针对 list 中的每个元素执行一次 body,并将变量 var 局部绑定为当前遍历到的元素。执行完成后,它会返回 result 的求值结果;若省略 result,则返回 nil。例如,以下是使用 dolist 定义 reverse 函数的方式:
(defun reverse (list)
(let (value)
(dolist (elt list value)
(setq value (cons elt value)))))
该结构会针对从 0(包含)到 count(不包含)的每个整数执行一次 body,并将变量 var 绑定为当前迭代对应的整数。执行完成后,它会返回 result 的求值结果;若省略 result,则返回 nil。不建议使用 result 参数。以下是使用 dotimes 执行某操作 100 次的示例:
(dotimes (i 100) (insert "I will not obey absurd orders\n"))