11.5 迭代

迭代是指重复执行程序的某一部分。例如,你可能想对列表中的每个元素执行一次计算,或者对从 0 到 n 的每个整数各执行一次。在 Emacs Lisp 中,可以使用特殊形式 while 来实现:

Special Form: while condition forms…

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)的实际操作)。

dolistdotimes 宏为两种常见循环类型提供了简洁的实现方式。

Macro: dolist (var list [result]) body…

该结构会针对 list 中的每个元素执行一次 body,并将变量 var 局部绑定为当前遍历到的元素。执行完成后,它会返回 result 的求值结果;若省略 result,则返回 nil。例如,以下是使用 dolist 定义 reverse 函数的方式:

(defun reverse (list)
  (let (value)
    (dolist (elt list value)
      (setq value (cons elt value)))))
Macro: dotimes (var count [result]) body…

该结构会针对从 0(包含)到 count(不包含)的每个整数执行一次 body,并将变量 var 绑定为当前迭代对应的整数。执行完成后,它会返回 result 的求值结果;若省略 result,则返回 nil。不建议使用 result 参数。以下是使用 dotimes 执行某操作 100 次的示例:

(dotimes (i 100)
  (insert "I will not obey absurd orders\n"))

emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© 2025 Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike