Types 如何正确指定可调整向量的元素类型

Types 如何正确指定可调整向量的元素类型,types,common-lisp,adjustable-array,Types,Common Lisp,Adjustable Array,下面是一个结构,它可以用作(后进先出)堆栈或(fifo)队列 内容范围从jvector启动到jvector填充指针。我希望能够使用以下内容指定内容的元素类型 (defun create-jvector (&key (element-type t)) (make-jvector :vector (make-array 0 :element-type element-type :adjustable t :fill-pointer 0) :start 0)

下面是一个结构,它可以用作(后进先出)堆栈或(fifo)队列

内容范围从jvector启动到jvector填充指针。我希望能够使用以下内容指定内容的元素类型

(defun create-jvector (&key (element-type t))
  (make-jvector :vector (make-array 0 :element-type element-type :adjustable t :fill-pointer 0)
                :start 0))
并用

(defun push-jvector (elt jvec)
  (vector-push-extend elt (jvector-vector jvec)))
但是,create jvector中的元素类型将被忽略。比如说,

* (defparameter v (create-jvector :element-type 'integer))
V
* v
#S(JVECTOR :VECTOR #() :START 0)
* (push-jvector 1 v)
0          ;OK result
* v
#S(JVECTOR :VECTOR #(1) :START 0)
* (push-jvector 'a v)
1          ;not OK result
* v
#S(JVECTOR :VECTOR #(1 A) :START 0)
为什么推送“a”不会产生类型错误,如何解决此问题?

为什么没有类型错误 根据阵列的
阵列元素类型检查类型:

(defparameter w (create-jvector :element-type 'fixnum))

(array-element-type (jvector-vector v))
=> T

(array-element-type (jvector-vector w))
=> FIXNUM
将符号按到
W
会导致错误。正如jkiiski所说,该类型主要用于帮助编译器有机会对数组(位向量、字符串等)使用专门的表示

integer
可以是bignum,这就是为什么升级后的元素类型为
T

(upgraded-array-element-type 'integer)
=> T
如何解决你的问题 这是jkiiski暗示的解决方案,即将类型添加到结构中;在这里,我还直接从结构中重新定义构造函数:

(defstruct (j2vector
             (:constructor make-jvector
                           (element-type
                            &aux
                            (start 0)
                            (vector (make-array 0
                                                :adjustable t
                                                :fill-pointer 0
                                                :element-type element-type)))))
  element-type
  vector
  (start 0 :type (integer 0)))
然后显式检查类型:

(defun push-jvector (elt jvec)
  (assert (typep elt (j2vector-element-type jvec)) ())
  (vector-push-extend elt (j2vector-vector jvec)))

如果您告诉
MAKE-ARRAY
一个元素类型,那么它将尝试分配一个节省空间的数组。实施通常支持一些变体:

示例:

CL-USER 13 > (mapcar #'upgraded-array-element-type
                     '(bit fixnum character))
((UNSIGNED-BYTE 1) (SIGNED-BYTE 64) CHARACTER)
但对于许多类型,没有节省空间的阵列:

CL-USER 14 > (mapcar #'upgraded-array-element-type
                     '(integer string standard-object))
(T T T)
您请求了一个整数数组,得到了一个常规数组:请参阅
升级的数组元素类型
返回的类型
T


它不是关于类型检查,而是关于要求运行时可能获得一个空间优化的数组。

数组元素类型主要是允许实现为基元类型优化数组存储。如果要检查任意类型的安全性,可以将类型说明符存储在结构中,并手动检查新元素是否属于
PUSH-JVECTOR
中的类型。不幸的是,CL不支持泛型/类型参数,因此没有编译时检查。我主要感兴趣的是获得高效的内部表示,而不是运行时安全性。但是,当您指定(debug 3)和(debug 0)之类的优化时,编译器只会增加/减少安全性(通过包括运行时检查),这样说对吗?也就是说,编译器优化不会影响数组存储或其他数据表示选择之类的事情?好的。我发现的唯一其他类型(除了您提到的类型外)是单浮点数、短浮点数、双浮点数、长浮点数、标准字符和NIL。@davypough:还有一些。通常会有无符号字节的变体:2、4、8、16、,32@davypough:signed byte alsoSo的变体,看起来原始的create jvector可以工作,只要我指定一个我知道可以有效表示的元素类型。您和jkiiski提到的替代构造函数是一个有趣的抽象。它是否可以用于允许最终用户/程序员对输入数据设置错误约束?
CL-USER 14 > (mapcar #'upgraded-array-element-type
                     '(integer string standard-object))
(T T T)