How to protect vector from resizing?
Asked Answered
P

2

5

So I am going through Practical Common Lisp once again and I cannot really understand how to create a vector with constant size.

According to the book:

However, even a vector with a fill pointer isn't completely resizable. The vector *x* can hold at most five elements. To make an arbitrarily resizable vector, you need to pass MAKE-ARRAY another keyword argument: :adjustable.

However when I use (vector-push-extend) I can extend my initial vector even when I set :adjustable nil (or leave it default).

(vector-push 'a *x*) ;; 0
(vector-push 'b *x*) ;; 1
(vector-push 'c *x*) ;; 2
(vector-push 'd *x*) ;; 3
(vector-push 'e *x*) ;; 4
*x* ;; #(A B C D E)
(vector-push 'f *x*) ;; NIL
*x* ;; #(A B C D E)
(vector-push-extend 'f *x*) ;; 5
*x* ;; #(A B C D E F)

I assumed that (vector-push-extend) cannot resize array which is not :adjustable? What is the correct way of creating non-dynamic (non-adjustable) array?

Penal answered 22/8, 2019 at 6:59 Comment(2)
which implementation are you using?Fanchette
I am using SBCL 1.5.5.Penal
F
6

The behavior is implementation specific.

The Common Lisp specification says:

There is no specified way to create an array for which adjustable-array-p definitely returns false.

An implementation may make vectors adjustable, even though the :adjustable argument to make-array is given as nil.

To see if an array object is actually adjustable, one needs to call adjustable-array-p.

The Common Lisp standard says that a vector is expressly adjustable (and thus also actually adjustable if it was requested to be so. If it wasn't request, the vector can still be adjustable, actually adjustable.

So the :adjustable nil arg is just telling Lisp, that it can make the vector non-adjustable, if possible.

Here in SBCL:

1) A normal vector is not adjustable:

* (make-array 5)
#(0 0 0 0 0)
* (adjustable-array-p *)
NIL

2) A vector with a fill-pointer is actually adjustable in SBCL:

* (make-array 5 :fill-pointer 0)
#()
* (adjustable-array-p *)
T

3) A vector with a fill-pointer is actually adjustable in SBCL, even though the :adjustable arg was given as nil:

* (make-array 5 :fill-pointer 0 :adjustable nil)
#()
* (adjustable-array-p *)
T

That's in SBCL. In LispWorks 2) and 3) would not be actually adjustable.

Fanchette answered 22/8, 2019 at 7:25 Comment(0)
S
6

The specification of make-array says that it is implementation dependent whether an array with :adjustable nil is actually adjustable. In the notes, it goes on to say:

There is no specified way to create an array for which adjustable-array-p definitely returns false.

So, it really depends on the implementation.

The correct way is to use vector-push if you do not want to extend.

Scotch answered 22/8, 2019 at 7:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.