1.8.4 使用错误类型的对象作为参数

当一个函数被传递一个错误类型的参数时,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这样的符号。但那样你就不会收到错误消息。


Footnotes

(4)

(quote hello)'hello缩写的扩展。