以下是旨在用作(lifo)堆栈或(fifo)队列的结构
(defstruct jvector
(vector (make-array 0 :adjustable t :fill-pointer 0) :type (array * (*)))
(start 0 :type (integer 0 *)))
的内容从jvector-start到jvector-vector填充指针。我希望能够用类似的东西指定内容的元素类型
(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不会产生类型错误,这将如何解决?
答案 0 :(得分:6)
如果您告诉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
返回的类型upgraded-array-element-type
。
这与类型检查无关,而是与要求运行时可能获得空间优化的数组有关。
答案 1 :(得分:4)
根据数组的array-element-type
检查类型:
(defparameter w (create-jvector :element-type 'fixnum))
(array-element-type (jvector-vector v))
=> T
(array-element-type (jvector-vector w))
=> FIXNUM
将符号推入W
会导致错误。正如jkiiski所说,该类型主要用于帮助编译器有机会对数组(位向量,字符串等)使用专门的表示形式。
integer
可以是大数字,这就是为什么升级后的元素类型为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)))