14.8 递归计算不同文件中的单词数

除了使用 while 循环外,你还可以通过递归来处理文件列表中的每个文件。一个递归版本的 lengths-list-many-files 很短而简单。

递归函数具有通常的部分:再次执行测试、下一步表达式和递归调用。再次执行测试确定函数是否应该再次调用自身,如果 list-of-files 包含任何剩余元素,它将调用自身;下一步表达式将 list-of-files 重置为其自身的 CDR,所以最终列表将为空;递归调用在较短的列表上调用自身。整个函数比这个描述还要短!

(defun recursive-lengths-list-many-files (list-of-files)
  "返回 LIST-OF-FILES 中每个 defun 的长度列表。"
  (if list-of-files                     ; 再次执行测试
      (append
       (lengths-list-file
        (expand-file-name (car list-of-files)))
       (recursive-lengths-list-many-files
        (cdr list-of-files)))))

简而言之,该函数返回第一个 list-of-files 的长度列表,附加到对其余 list-of-files 调用自身的结果上。

这里是对 recursive-lengths-list-many-files 的测试,以及在每个文件上分别运行 lengths-list-file 的结果。

如果需要,安装 recursive-lengths-list-many-fileslengths-list-file,然后评估以下表达式。您可能需要更改文件的路径;这些路径在此 Info 文件和 Emacs 源代码位于其习惯位置时有效。要更改表达式,将其复制到 *scratch* 缓冲区,编辑它们,然后评估它们。

结果在 ‘’ 之后显示。(这些结果是针对 Emacs 版本 22.1.1 的文件;来自其他版本的 Emacs 的文件可能会产生不同的结果。)

(cd "/usr/local/share/emacs/22.1.1/")

(lengths-list-file "./lisp/macros.el")
     ⇒ (283 263 480 90)

(lengths-list-file "./lisp/mail/mailalias.el")
     ⇒ (38 32 29 95 178 180 321 218 324)

(lengths-list-file "./lisp/hex-util.el")
     ⇒ (82 71)

  (recursive-lengths-list-many-files
   '("./lisp/macros.el"
     "./lisp/mail/mailalias.el"
     "./lisp/hex-util.el"))
       ⇒ (283 263 480 90 38 32 29 95 178 180 321 218 324 82 71)

recursive-lengths-list-many-files 函数产生了我们想要的输出。

下一步是准备列表中的数据以在图表中显示。