Published: 2018-05-24

Common lisp运行时检查变量类型

在Common lisp里,可以采用如下几种方式在运行的时候检查变量类型。

Table of Contents

1 CHECK-TYPE

Macro CHECK-TYPE

;; 语法:
check-type place typespec [string] => nil


;; 作用:
检查第一个参数的类型是否是第二个参数所指定的类型。



;; 示例:
CL-USER> (defun my-sqrt (x)
           (check-type x (real 0))
           (sqrt x))
MY-SQRT

CL-USER> (my-sqrt 9)
3.0

CL-USER> (my-sqrt -9)
Type a form to be evaluated: 4

2.0

CL-USER> (check-type 9 (real 0))
                                        ; in: CHECK-TYPE 9
                                        ;     (SETF 9 (SB-KERNEL:CHECK-TYPE-ERROR '9 #:G599 '(REAL 0)))
                                        ; ==>
                                        ;   (SETQ 9 (SB-KERNEL:CHECK-TYPE-ERROR '9 #:G599 '(REAL 0)))
                                        ;
                                        ; caught ERROR:
                                        ;   Variable name is not a symbol: 9.
                                        ;
                                        ; compilation unit finished
                                        ;   caught 1 ERROR condition
NIL



;; 注意点:
a. 第一个参数会被求值,第二个参数不会被求值
b. 第一个参数不能只是普通的变量,其应当可以被setf设置
c. 如果第一个参数的类型不满足第二个参数指定的类型,那么会产生一个 TYPE-ERROR
d. 产生 TYPE-ERROR 后提供一个restart选项,可以提供一个其他值作为第一个参数
e. check-type 的第三个参数是优化产生error后的提示信息

2 TYPEP

Function TYPEP

;; 语法:
typep object type-specifier &optional environment => generalized-boolean


;; 作用:
检查object是否有type-specifier的类型


;; 注意点:
a. 不像check-type,typep是个函数,两个参数都会被求值,所以第二个类型参数需要quote传入
b. check-type不满足类型会产生error, typep会返还nil
c. typep的第一个检查的参数不像check-type那样有限制

3 TYPE-OF

Function TYPE-OF

;; 语法:
type-of object => typespec


;; 作用:
返回object的类型


;;注意:
不同lisp实现之间的返回值可能不一致,如果追求可移植性,不建议使用

4 其它

;; 1. 在一些lisp实现比如sbcl里,可以采用 declare 等来确保变量类型, 如下

(defun my-sqrt (x)
  (declare (type (real 0) x))
  (sqrt x))

如果x为负数,那么会触发一个error,但没有restart选项。
但declare的可移植性是没法保证的。



;; 2. typecase等,留待以后探究

Author: Nisen

Email: imnisen@163.com

Emacs 25.2.1 (Org mode 8.2.10)