我尝试了sbcl 1.1.14中的以下代码,但似乎类型检查忽略了vector元素的声明。
(defun test (vec)
(declare (type (vector integer) vec))
(format nil "~a~&" (elt vec 0)))
有什么提示吗?谢谢!
首先请注意,将声明用作类型检查不是标准ANSI Common Lisp提供的内容。这是CMUCL引入的扩展。SBCL是CMUCL的后代。
Common Lisp类型系统用于向量和数组的方式有点不寻常。
元素类型。
正在使用元素类型创建数组。这意味着Lisp系统将创建一个可以存储该类型元素的数组。但是Common Lisp并不要求每种元素类型都有专门的数组版本。如果没有专用版本的数组,则元素类型将升级为下一个“更大”的类型。
元素类型升级示例
CL-USER 14 > (upgraded-array-element-type '(unsigned-byte 1))
(UNSIGNED-BYTE 1)
CL-USER 15 > (upgraded-array-element-type '(unsigned-byte 2))
(UNSIGNED-BYTE 2)
因此,存在针对(unsigned-byte 1)
和优化的数组版本(unsigned-byte 2)
。
CL-USER 16 > (upgraded-array-element-type '(unsigned-byte 3))
(UNSIGNED-BYTE 4)
哎呀!没有针对进行优化的数组(unsigned-byte 3)
。如果请求这样的数组,则将得到一个稍大的数组(unsigned-byte 4)
。
CL-USER 17 > (upgraded-array-element-type '(unsigned-byte 4))
(UNSIGNED-BYTE 4)
CL-USER 18 > (upgraded-array-element-type '(unsigned-byte 5))
(UNSIGNED-BYTE 8)
CL-USER 19 > (upgraded-array-element-type 'integer)
T
上面显示没有针对整数的特殊数组。您将获得一个通用数组。
您的密码
(defun test (vec)
(declare (type (vector integer) vec))
(format nil "~a~&" (elt vec 0)))
因此,您在这里的声明确实意味着:
变量vec
绑定到可以保存integer
数字的向量。
这并不意味着:
变量vec
绑定到仅包含integer
数字的向量。
CL-USER 21 > (typep '#(a "b" #\c) '(vector integer))
T
上面的代码在我的Lisp中返回true,因为向量是通用向量,并且可以存储整数。因此,它检查向量的类型,但是并不关心向量的内容是否实际上全部是整数类型。只是说,向量可以包含整数。
基于谓词的类型检查
Common Lisp允许类型声明使用谓词。
CL-USER 28 > (defun vector-of-numbers-p (vector)
(and (typep vector 'vector)
(every 'integerp vector)))
VECTOR-OF-NUMBERS-P
CL-USER 29 > (typep '#(a "b" #\c) '(satisfies arrayp))
T
CL-USER 30 > (typep '#(a "b" #\c) '(satisfies vector-of-numbers-p))
NIL
CL-USER 31 > (typep '#(1 2 3) '(satisfies vector-of-numbers-p))
T
但是在编译时检查一下吗?可能不是。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句