Types – how to specify the element type in the vector of SbCl (or common LISP)?

I tried in SbCl 1.1 14, but it seems that type checking ignores the declaration of the vector element

(defun test (vec)
  (declare (type (vector integer) vec))
  (format nil "~a~&" (elt vec 0)))

Any tips? thank you!

Solution

First, note that declaration as type checking is not provided by standard ANSI Common Lisp This is an extension introduced by cmucl SbCl is a descendant of cmucl

The Common Lisp type system applies to vectors and arrays in a somewhat unusual way

Element type

Creating array with element type This means that the LISP system will create an array that can store elements of this type However, Common Lisp does not require a special array version for each element type If a particular version of the array is not available, the element type is promoted to the next "larger" type

Element type upgrade example

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)

Therefore, there are array versions optimized for (unsigned byte 1) and (unsigned byte 2)

CL-USER 16 > (upgraded-array-element-type '(unsigned-byte 3))
(UNSIGNED-BYTE 4)

OOPS! There is no array optimized for (unsigned byte 3) If you request such an array, you will get a slightly larger array (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

The figure above shows that integers have no special array You'll get a generic array

Your code

(defun test (vec)
  (declare (type (vector integer) vec))
  (format nil "~a~&" (elt vec 0)))

So your statement really means:

The variable VEC is bound to a vector that can hold integers

This does not mean:

The variable VEC is bound to a vector that holds only integers

CL-USER 21 > (typep '#(a "b" #\c) '(vector integer))
T

The above returns true in my lisp, because the vector is a general vector, which can store integers So it checks the type of vector, but it doesn't care whether the contents of the vector are actually integer types It just says that the vector could contains integers

Predicate based type checking

Common Lisp allows type declarations to use predicates

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

But check it at compile time? Maybe not

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>