How does one properly specify the common-lisp type of an extendable vector (ie, acceptable to vector-push-extend), so it can be copied. For example, if a vector is defined by:
(defparameter v (make-array 2
:initial-contents '((a (b)) (c (d) e))
:adjustable t
:fill-pointer t))
My simple (incorrect) approach for copying it is:
(map 'array #'copy-tree v)
but this generates a type error in sbcl. Can a proper sequence type specification make this work?
You could simply do this:
(map (type-of v) #'copy-tree v)
What is the type?
CL-USER> (type-of v)
(VECTOR T 2)
The following is sufficient:
(map 'vector #'copy-tree v)
This graph is helpful to remember type hierarchies, notably arrays and vectors.
However, the resulting vectors are not adjustable. Maybe something like this can help:
(defun my-copy (vector)
(map-into (make-array (array-dimensions vector)
:adjustable (adjustable-array-p vector)
:fill-pointer (fill-pointer vector))
#'copy-tree
vector))
MAP needs as a result type a sequence type specifier. ARRAY is not one. Examples for subtypes of SEQUENCE are VECTOR and LIST.
The type declaration syntax for a VECTOR is: vector [{element-type | *} [{size | *}]].
There is no way to specify features like adjustable, fill pointer, displacement, ... in a vector type declaration. Corresponding feature options are also not provided as keywords to the function make-sequence. Also copy-seq will not create vectors with such features. To create such vectors you have to use MAKE-ARRAY.
Thus the options are:
MAKE-ARRAY and use functions like MAP-INTO -> see the excellent answer from coredump.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With