资源介绍
上一节我们定义的 our-member 以五个括号结尾。更复杂的函数定义可能以七、八个括号
结尾。刚学 Lisp 的人看到这么多括号会感到气馁。这叫人怎么读这样的程序,更不用说编
了?这叫人怎么知道哪个括号该跟哪个匹配?
答案是,你不需要这么做。 Lisp 程序员用缩排来阅读及编写程序,而不是括号。当他们在
写程序时,他们让文字编辑器显示哪个括号该与哪个匹配。任一个好的文字编辑器,特别是
Lisp 系统自带的,都应该能做到括号匹配 (paren-matching)。在这种编辑器中,当你输
入一个括号时,编辑器指出与其匹配的那一个。如果你的编辑器不能匹配括号,别用了,想
想如何让它做到,因为没有这个功能,你根本不可能编 Lisp 程序 [1] 。
[1] 在 vi,你可以用 :set sm 来启用括号匹配。在 Emacs,M-x lisp-mode 是一个启用的好方法。
有了好的编辑器,括号匹配不再是个问题。而且因为 Lisp 缩排有通用的惯例,阅读程序也
不是个问题。因为所有人都使用一样的习惯,你可以忽略那些括号,通过缩排来阅读程序。
任何有经验的 Lisp 黑客,会发现如果是这样的 our-member 的定义很难阅读:
1
2
(defun our-member (obj lst) (if (null lst) nil (if
(eql (car lst) obj) lst (our-member obj (cdr lst)))))
但如果程序适当地缩排时,他就没有问题了。你可以忽略大部分的括号而仍能读懂它:
1
2
3
4
5
6
defun our-member (obj lst)
if null lst
nil
if eql (car lst) obj
lst
our-member obj (cdr lst)
事实上,这是一个你在纸上写 Lisp 程序的实用方法。等你输入的时候,可以利用编辑器匹
配括号的功能。
2.9 输入输出 (Input and Output)
到目前为止,我们已经利用顶层偷偷使用了 I/O 。对实际的交互程序来说,这似乎还是不太
够。在这一节,我们来看看几个输入输出的函数。