有人可以解释一下以下两种情况之间的区别吗(特别是对于我来说,如果我无法理解的话,这些评论是怎么说的),它们来自功能方面的CLHS :
;; This function assumes its callers have checked the types of the
;; arguments, and authorizes the compiler to build in that assumption.
(defun discriminant (a b c)
(declare (number a b c))
"Compute the discriminant for a quadratic equation."
(- (* b b) (* 4 a c))) => DISCRIMINANT
(discriminant 1 2/3 -2) => 76/9
;; This function assumes its callers have not checked the types of the
;; arguments, and performs explicit type checks before making any assumptions.
(defun careful-discriminant (a b c)
"Compute the discriminant for a quadratic equation."
(check-type a number)
(check-type b number)
(check-type c number)
(locally (declare (number a b c))
(- (* b b) (* 4 a c)))) => CAREFUL-DISCRIMINANT
(careful-discriminant 1 2/3 -2) => 76/9
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实现将类型声明用于各种事物,并且它们对它们的处理高度依赖于实现。
(declare (type ...))
Common Lisp编译器中静态类型声明的主要用法是:
无视他们。通常,Lisp解释器和某些编译器会完全忽略它们
使用它们进行速度和空间优化。这是由许多编译器完成的。他们可以使用这些类型声明来创建专门的代码。
使用它们进行运行时类型检查。一些实现将类型声明用于运行时检查。
使用它们进行编译时类型检查。一些实现将类型声明用于编译时类型检查。例子是sbcl和cmucl。
请注意,Common Lisp标准没有说明如何使用这些类型声明。它只是提供了一种定义和声明类型的语法。然后,普通的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)))
; in: DEFUN SUBTRACT
; (CONCATENATE 'STRING A "-" B " is " (- A B))
;
; caught WARNING:
; Derived type of (SB-KERNEL:SYMEVAL 'A) is
; (VALUES NUMBER &OPTIONAL),
; conflicting with its asserted type
; SEQUENCE.
; See also:
; The SBCL Manual, Node "Handling of Types"
;
; compilation unit finished
; caught 1 WARNING condition
SUBTRACT
如您所见,我们正在尝试使用数字作为序列。SBCL在编译时检测到该情况并发出警告。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句