Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to protect vector from resizing?

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?

like image 506
dptd Avatar asked Aug 22 '19 06:08

dptd


1 Answers

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.

like image 82
Rainer Joswig Avatar answered Sep 23 '22 08:09

Rainer Joswig