将两个向量与填充指针合并到结果向量中

Tho*_*ier 3 merge vector common-lisp fill-pointer

我有两个带有填充指针的向量。我需要merge这些向量,因此需要一个仍然具有填充指针的新向量。

(defparameter *a* (make-array 3 :fill-pointer 3
                                :initial-contents '(1 3 5)))
(defparameter *b* (make-array 3 :fill-pointer 3
                                :initial-contents '(0 2 4)))
(type-of *a*)
;;=> (VECTOR T 6)

;; Pushing new elements works as intended.
(vector-push-extend 7 *a*)
(vector-push-extend 6 *b*)
;; Now we create a new vector by merging *a* and *b*.
(defparameter *c* (merge 'vector *a* *b* #'<))
;;=> #(0 1 2 3 4 5 6 7)
(type-of *c*)
;;=> (SIMPLE-VECTOR 8)

;; The type of this new vector does not allow pushing elements.
(vector-push-extend 8 *c*)

;; The value
;;   #(0 1 2 3 4 5 6 7)
;; is not of type
;;   (AND VECTOR (NOT SIMPLE-ARRAY))
;;    [Condition of type TYPE-ERROR]
Run Code Online (Sandbox Code Playgroud)

我似乎找不到要指定要合并的类型,以便结果将具有填充指针。我想显而易见的解决方法是:

  • merge自己编写一个函数,该函数声明一个新的向量并以正确的顺序执行插入。
  • 使用填充指针将结果复制到另一个向量中。

当然,如果有一种方法可以merge从标准中使用,则两种解决方法都不能令人满意。

sds*_*sds 6

确实,没有简单的方法可以通过填充指针获得merge return a vector

但是,您可以将向量替换为结果:

(defparameter *c* (merge '(vector t) *a* *b* #'<))
(type-of *c*)
==> (SIMPLE-VECTOR 8)
(defparameter *d* (make-array (length *c*) :displaced-to *c* :fill-pointer t))
(type-of *d*)
==> (VECTOR T 8)
*d*
==> #(0 1 2 3 4 5 6 7)
(array-displacement *d*)
==> #(0 1 2 3 4 5 6 7); 0
(vector-push-extend 17 *d*)
==> 8
*d*
==> #(0 1 2 3 4 5 6 7 17)
Run Code Online (Sandbox Code Playgroud)

到目前为止一切顺利,对吗?

不,不是那么快:

(array-displacement *d*)
==> NIL; 0
Run Code Online (Sandbox Code Playgroud)

当我们调用vector-push-extend*d*,由于底层simple-vector 不能扩展,所以它已从置换数组转换为普通数组。

如果要使用列表,则可能实际上考虑使用列表而不是数组,merge因为它在列表上效率更高(重用结构)。