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
函数,它值得有一个专门的小节。