use*_*284 3 types sbcl common-lisp
我尝试在sbcl 1.1.14中使用代码,但似乎类型检查忽略了vector元素的声明.
(defun test (vec)
(declare (type (vector integer) vec))
(format nil "~a~&" (elt vec 0)))
Run Code Online (Sandbox Code Playgroud)
任何提示?谢谢!
Rai*_*wig 12
首先请注意,将声明作为类型检查不是标准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)
Run Code Online (Sandbox Code Playgroud)
因此有针对(unsigned-byte 1)
和优化的阵列版本(unsigned-byte 2)
.
CL-USER 16 > (upgraded-array-element-type '(unsigned-byte 3))
(UNSIGNED-BYTE 4)
Run Code Online (Sandbox Code Playgroud)
OOPS!没有优化的阵列(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
Run Code Online (Sandbox Code Playgroud)
上图显示整数没有特殊数组.你会得到一个通用数组.
你的守则
(defun test (vec)
(declare (type (vector integer) vec))
(format nil "~a~&" (elt vec 0)))
Run Code Online (Sandbox Code Playgroud)
所以你的声明真的意味着:
变量vec
绑定到一个可以保存integer
数字的向量.
这并不意味着:
变量vec
绑定到一个只保存integer
数字的向量.
CL-USER 21 > (typep '#(a "b" #\c) '(vector integer))
T
Run Code Online (Sandbox Code Playgroud)
以上在我的Lisp中返回true,因为向量是一般向量,它可以存储整数.因此它会检查向量的类型,但它并不关心向量的内容是否实际上都是整数类型.它只是说,向量COULD包含整数.
基于谓词的类型检查
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
Run Code Online (Sandbox Code Playgroud)
但是在编译时检查一下?可能不是.