Emacs Lisp 解释器本身不会在函数调用时,对传递给函数的实际参数执行类型检查。这是因为 Lisp 中的函数参数不像其他编程语言那样有声明的数据类型,因此解释器无法完成这类检查。故而,需要由各个函数自行检验每个实际参数是否属于该函数可处理的类型。
所有内置函数都会在适当时机检查其实际参数的类型;若参数类型错误,会触发 wrong-type-argument 错误。例如,向 + 函数传入其无法处理的参数时,会出现如下情况:
(+ 2 'a)
error→ Wrong type argument: number-or-marker-p, a
若希望程序根据不同类型执行不同逻辑,必须显式进行类型检查。检查对象类型最常用的方式是调用 type predicate类型谓词 函数。Emacs 为每种类型都提供了对应的类型谓词,同时也包含一些针对类型组合的谓词。
类型谓词函数接收一个参数:若该参数属于对应类型,则返回 t,否则返回 nil。遵循 Lisp 谓词函数的通用约定,大多数类型谓词的名称以 ‘p’ 结尾。
以下示例使用谓词 listp 检查列表类型、symbolp 检查符号类型:
(defun add-on (x)
(cond ((symbolp x)
;; If X is a symbol, put it on LIST.
(setq list (cons x list)))
((listp x)
;; If X is a list, add its elements to LIST.
(setq list (append x list)))
(t
;; We handle only symbols and lists.
(error "Invalid argument %s in add-on" x))))
下表按字母顺序列出了预定义的类型谓词,并标注了进一步说明的引用位置:
atomSee atom.
arraypSee arrayp.
bignumpSee bignump.
bool-vector-pSee bool-vector-p.
booleanpSee booleanp.
bufferpSee bufferp.
byte-code-function-pSee byte-code-function-p.
case-table-pSee case-table-p.
char-or-string-pSee char-or-string-p.
char-table-pSee char-table-p.
closurepSee closurep.
commandpSee commandp.
compiled-function-pSee compiled-function-p.
condition-variable-pSee condition-variable-p.
conspSee consp.
custom-variable-pSee custom-variable-p.
fixnumpSee fixnump.
floatpSee floatp.
fontpframe-configuration-pframe-live-pSee frame-live-p.
framepSee framep.
functionpSee functionp.
hash-table-pSee hash-table-p.
integer-or-marker-pSee integer-or-marker-p.
integerpSee integerp.
interpreted-function-pkeymappSee keymapp.
keywordpSee 永不改变的变量.
listpSee listp.
markerpSee markerp.
mutexpSee mutexp.
nlistpSee nlistp.
number-or-marker-pSee number-or-marker-p.
numberpSee numberp.
obarraypSee obarrayp.
overlaypSee overlayp.
processpSee processp.
recordpSee recordp.
sequencepSee sequencep.
string-or-null-pSee string-or-null-p.
stringpSee stringp.
subrpSee subrp.
symbolpSee symbolp.
syntax-table-pSee syntax-table-p.
threadpSee threadp.
vectorpSee vectorp.
wholenumpSee wholenump.
window-configuration-pwindow-live-pSee window-live-p.
windowpSee windowp.
检查对象类型最通用的方式是调用 type-of 函数。需注意,每个对象仅属于一种原始类型; type-of 会返回该对象所属的原始类型(see Lisp 数据类型)。但 type-of 无法识别非原始类型,因此在大多数情况下,使用类型谓词比 type-of 更合适。
该函数返回一个符号,代表 object 的原始类型。返回值为以下符号之一:
bool-vector,
buffer, char-table, compiled-function,
condition-variable, cons, finalizer,
float, font-entity, font-object,
font-spec, frame, hash-table, integer,
marker, mutex, obarray, overlay, process,
string, subr, symbol, thread,
vector, window, or window-configuration。
但如果 object 是记录(record),则返回其第一个槽位指定的类型;记录。
(type-of 1)
⇒ integer
(type-of 'nil)
⇒ symbol
(type-of '()) ; () is nil.
⇒ symbol
(type-of '(x))
⇒ cons
(type-of (record 'foo))
⇒ foo
该函数返回一个符号,代表 object 的类型。其行为通常与 type-of 一致,但会保证返回尽可能精确的类型 —— 这也意味着,它返回的具体类型可能随 Emacs 版本变化。因此,原则上不应将其返回值与固定的类型集合做比较。
(cl-type-of 1)
⇒ fixnum
(cl-type-of 'nil)
⇒ null
(cl-type-of (record 'foo))
⇒ foo