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

dav*_*ugh 2 types common-lisp adjustable-array

以下是旨在用作(lifo)堆栈或(fifo)队列的结构

(defstruct jvector
  (vector (make-array 0 :adjustable t :fill-pointer 0) :type (array * (*)))
  (start 0 :type (integer 0 *)))
Run Code Online (Sandbox Code Playgroud)

内容的范围从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))
Run Code Online (Sandbox Code Playgroud)

并用

(defun push-jvector (elt jvec)
  (vector-push-extend elt (jvector-vector jvec)))
Run Code Online (Sandbox Code Playgroud)

但是,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)
Run Code Online (Sandbox Code Playgroud)

为什么推'a不会产生类型错误,什么可以解决?

Rai*_*wig 6

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

例子:

CL-USER 13 > (mapcar #'upgraded-array-element-type
                     '(bit fixnum character))
((UNSIGNED-BYTE 1) (SIGNED-BYTE 64) CHARACTER)
Run Code Online (Sandbox Code Playgroud)

但是对于许多类型,没有节省空间的数组:

CL-USER 14 > (mapcar #'upgraded-array-element-type
                     '(integer string standard-object))
(T T T)
Run Code Online (Sandbox Code Playgroud)

您需要一个整数数组并获得了一个通用数组:请参阅T返回的类型upgraded-array-element-type

这与类型检查无关,而与要求运行时可能获得空间优化的数组有关。