CHECK-TYPE : 运行时类型检查和修复
check-type
实际上进行运行时检查。通常还提供一种交互式修复值的方法。
* (let ((a "1"))
(check-type a number)
(+ a 2))
debugger invoked on a SIMPLE-TYPE-ERROR in thread
#<THREAD "main thread" RUNNING {10005184C3}>:
The value of A is "1", which is not of type NUMBER.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [STORE-VALUE] Supply a new value for A.
1: [ABORT ] Exit debugger, returning to top level.
(SB-KERNEL:CHECK-TYPE-ERROR A "1" NUMBER NIL)
0] 0
Enter a form to be evaluated: 1
3
DECLARE: 类型声明
Common Lisp是动态类型语言:每个数据对象都有一个类型。
Common Lisp还允许使用静态类型来定义变量和函数。以下是一些相关的概念:
- 各种类型和复合类型
- 使用
deftype
来定义新类型
- 使用
declare
进行类型声明
- 使用
subtypep
进行子类型检查
- 使用
typep
进行运行时类型检查
- 使用
typecase
、ctypecase
和 etypecase
进行运行时条件类型判断
现在,Common Lisp实现使用类型声明来做很多事情,它们对这些类型声明的处理高度依赖于具体实现。
在Common Lisp编译器中,使用静态类型声明(declare (type ...))
的主要用途包括:
忽略它们。通常Lisp解释器和某些编译器完全忽略它们。
用于速度和空间优化。许多编译器都会这样做。它们可以使用这些类型声明来创建专用代码。
用于运行时类型检查。某些实现使用类型声明进行运行时检查。
用于编译时类型检查。某些实现使用类型声明进行编译时类型检查,如sbcl和cmucl。
需要注意的是,Common Lisp标准并未说明这些类型声明的具体使用方式。它只提供了定义和声明类型的语法。Common Lisp实现要么使用它们,要么忽略它们。
SBCL和CMUCL尤其是能够实现复杂的类型声明。
类型检查示例
让我们看看SBCL如何使用类型声明来进行运行时和编译时类型检查:
使用SBCL进行运行时类型检查:
* (defun add (a b)
(declare (type number a b))
(list a b))
ADD
* (add 1 "3")
debugger invoked on a TYPE-ERROR in thread
#<THREAD "main thread" RUNNING {10005184C3}>:
The value
"3"
is not of type
NUMBER
when binding B
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(ADD 1 "3") [external]
source: (SB-INT:NAMED-LAMBDA ADD
(A B)
(DECLARE (TYPE NUMBER A B))
(BLOCK ADD (LIST A B)))
0]
我们可以看到,SBCL使用类型声明进行运行时检查。但与check-type
不同的是,它没有提供提供不同的值和相应的重新检查...
使用SBCL进行编译时类型检查:
* (defun subtract (a b)
(declare (type number a b))
(concatenate 'string a "-" b " is " (- a b)))
SUBTRACT
正如您所看到的,我们正在尝试使用数字作为序列。SBCL 在编译时检测到并发出警告。
subtract
的实际意图,为什么要将函数参数声明为数字,并在函数体中将它们用作字符串?但如果我理解正确,在与您的第一个函数add
结合使用时,其中主体中的操作与args的类型无关(list
ing),应该表明编译器在编译时进行类型检查。 - Student