除了使用 while 循环,你也可以通过递归方式处理文件列表中的每一个文件。lengths-list-many-files 的递归版本简洁短小。
递归函数包含常规组成部分:继续执行判断条件、步进表达式,以及递归调用。继续执行判断条件决定函数是否需要再次调用自身——当 list-of-files 中仍有剩余元素时便会继续;步进表达式将 list-of-files 重置为自身的 CDR,最终列表会变为空;递归调用则在更短的列表上执行自身。完整的函数比这段描述还要简短!
(defun recursive-lengths-list-many-files (list-of-files)
"Return list of lengths of each defun in LIST-OF-FILES."
(if list-of-files ; do-again-test
(append
(lengths-list-file
(expand-file-name (car list-of-files)))
(recursive-lengths-list-many-files
(cdr list-of-files)))))
简单来说,该函数先获取 list-of-files 中第一个文件的长度列表,再将其与自身在剩余文件上调用的结果拼接起来。
下面是对 recursive-lengths-list-many-files 的测试,同时分别展示在各个文件上运行 lengths-list-file 的结果。
如有需要,先加载 recursive-lengths-list-many-files 和 lengths-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 函数输出了我们需要的结果。
下一步是将列表中的数据整理为适合图表展示的形式。