确定 defuns 的长度

使用 while 循环的设计是常规的。传递给函数的参数是一个文件列表。正如我们之前看到的 (see 使用 while 循环和列表),可以编写一个 while 循环,使得在列表包含元素的情况下计算循环体,但在列表为空时退出循环。为了使此设计工作,循环体必须包含一个表达式,该表达式在每次计算循环体时缩短列表,以便最终列表为空。通常的技术是在每次计算循环体时将列表的值设置为列表的 CDR 的值。

模板如下:

(while 测试列表是否为空
  循环体设置列表为列表的cdr)

此外,我们要记住,while 循环返回 nil(真假测试的计算结果),而不是循环体内任何评估的结果。(循环体内的评估是为了它们的副作用。)然而,设置长度列表的表达式是循环体的一部分,这是我们希望整个函数返回的值。为了实现这一点,我们将 while 循环封装在一个 let 表达式内,并安排 let 表达式的最后一个元素包含长度列表的值。(See 带有增量计数器的循环示例.)

这些考虑直接引导我们到函数本身:

;;; 使用 while 循环。
(defun lengths-list-many-files (list-of-files)
  "返回 LIST-OF-FILES 中 defuns 的长度列表。"
  (let (lengths-list)

;;; 真假测试
    (while list-of-files
      (setq lengths-list
            (append
             lengths-list

;;; 生成长度列表。
             (lengths-list-file
              (expand-file-name (car list-of-files)))))

;;; 使文件列表变短。
      (setq list-of-files (cdr list-of-files)))

;;; 返回长度列表的最终值。
    lengths-list))

expand-file-name 是一个内置函数,将文件名转换为绝对路径形式。该函数使用调用函数所在目录的名称。

因此,如果在 Emacs 访问 /usr/local/share/emacs/22.1.1/lisp/emacs-lisp/ 目录时,对 debug.el 调用 expand-file-name

debug.el

变成了

/usr/local/share/emacs/22.1.1/lisp/emacs-lisp/debug.el

该函数定义的另一个新元素是尚未学习的 append 函数,它值得有一个专门的小节。