当一个函数被传递一个错误类型的参数时,Lisp解释器会产生一个错误消息。例如,+
函数期望其参数的值为数字。作为实验,我们可以传递给它带引号的符号hello
,而不是一个数字。将光标放在以下表达式后,然后输入C-x C-e:
(+ 2 'hello)
当你这样做时,将生成一个错误消息。发生的情况是,+
试图将2添加到'hello
返回的值,但'hello
返回的值是符号hello
,而不是一个数字。只有数字可以相加。所以+
无法执行其加法运算。
你将创建并进入一个*Backtrace*缓冲区,其中显示:
---------- Buffer: *Backtrace* ---------- Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p hello) +(2 hello) eval((+ 2 'hello) nil) elisp--eval-last-sexp(t) eval-last-sexp(nil) funcall-interactively(eval-print-last-sexp nil) call-interactively(eval-print-last-sexp nil nil) command-execute(eval-print-last-sexp) ---------- Buffer: *Backtrace* ----------
和往常一样,错误消息试图提供帮助,并在学会如何阅读后变得有意义。4
错误消息的第一部分很简单,它说‘wrong type argument’。接下来是神秘的行话词‘number-or-marker-p’。这个词试图告诉你+
期望的参数类型。
符号number-or-marker-p
表示Lisp解释器正在尝试确定所呈现的信息(参数的值)是一个数字还是一个标记(表示缓冲区位置的特殊对象)。它的操作是测试+
是否被赋予要相加的数字。它还测试参数是否是一种称为标记的东西,这是Emacs Lisp的一个特定特性。(在Emacs中,缓冲区中的位置被记录为标记。当使用C-@或C-SPC命令设置标记时,其位置被保留为标记。标记可以被视为一个数字—表示该位置距离缓冲区开头的字符数。在Emacs Lisp中,+
可以用于将标记位置的数值作为数字相加。
number-or-marker-p
中的‘p’体现了Lisp编程早期实践的一种做法。‘p’代表谓词。在早期Lisp研究者使用的行话中,谓词是指一个函数,用于确定某个属性是否为真或为假。因此,‘p’告诉我们number-or-marker-p
是一个函数的名称,该函数确定所提供的参数是否为数字或标记。其他以‘p’结尾的Lisp符号包括zerop
,一个测试其参数是否为零值的函数,以及listp
,一个测试其参数是否为列表的函数。
最后,错误消息的最后部分是符号hello
。这是传递给+
的参数的值。如果相加操作传递了正确类型的对象,传递的值将是一个数字,如37,而不是像hello
这样的符号。但那样你就不会收到错误消息。