(lispkit vector)

Vectors are heterogeneous data structures whose elements are indexed by a range of integers. A vector typically occupies less space than a list of the same length, and a randomly chosen element can be accessed in constant time vs. linear time for lists.

The length of a vector is the number of elements that it contains. This number is a non-negative integer that is fixed when the vector is created. The valid indexes of a vector are the exact, non-negative integers less than the length of the vector. The first element in a vector is indexed by zero, and the last element is indexed by one less than the length of the vector.

Two vectors are equal? if they have the same length, and if the values in corresponding slots of the vectors are equal?.

A vector can be mutable or immutable. Trying to change the state of an immutable vector, e.g. via vector-set! will result in an error being raised.

Vectors are written using the notation #(obj ...). For example, a vector of length 3 containing the number zero in element 0, the list (1 2 3 4) in element 1, and the string "Lisp" in element 2 can be written as follows: #(0 (1 2 3 4) "Lisp").

Vector constants are self-evaluating, so they do not need to be quoted in programs. Vector constants, i.e. vectors created with a vector literal, are immutable.

LispKit also supports growable vectors via library (lispkit gvector). As opposed to regular vectors, a growable vector does not have a fixed size and supports adding and removing elements. While a growable vector does not satisfay the vector? predicate, this library also accepts growable vectors as parameters whenever a vector is expected. Use predicate mutable-vector? for determining whether a vector is either a regular mutable vector or a growable vector.

Predicates

Returns #t if obj is a regular vector; otherwise returns #f. This function returns #f for growable vectors; see library (lispkit gvector).

Returns #t if obj is either a mutable regular vector or a growable vector (see library (lispkit gvector)); otherwise returns #f.

Returns #t if obj is an immutable vector; otherwise returns #f.

Procedure vector= is a generic comparator for vectors. Vectors a and b are considered equal by vector= if their lengths are the same, and for each respective elements ai and bi, (eql ai bi) evaluates to true. eql is always applied to two arguments.

If there are only zero or one vector argument, #t is automatically returned. The dynamic order in which comparisons of elements and of vectors are performed is unspecified.

(vector= eq? #(a b c d) #(a b c d))  ⇒  #t 
(vector= eq? #(a b c d) #(a b d c))  ⇒  #f 
(vector= = #(1 2 3 4 5) #(1 2 3 4))  ⇒  #f 
(vector= = #(1 2 3 4) #(1.0 2.0 3.0 4.0))  ⇒  #t 
(vector= eq?) ⇒  #t 
(vector= eq? '#(a))  ⇒  #t 

Constructors

Returns a newly allocated vector of k elements. If a second argument is given, then each element is initialized to fill. Otherwise the initial contents of each element is unspecified.

Returns a newly allocated mutable vector whose elements contain the given arguments. It is analogous to list.

(vector ’a ’b ’c)  ⇒  #(a b c)

Returns a newly allocated immutable vector whose elements contain the given arguments in the given order.

The list->vector procedure returns a newly created mutable vector initialized to the elements of the list list in the order of the list.

(list->vector ’(a b c))  ⇒  #(a b c)

The list->vector procedure returns a newly created immutable vector initialized to the elements of the list list in the order of the list.

The string->vector procedure returns a newly created mutable vector initialized to the elements of the string str between start and end (i.e. including all characters from index start to index end-1).

(string->vector "ABC")  ⇒  #(#\A #\B #\C)

Returns a newly allocated copy of the elements of the given vector between start and end, but excluding the element at index end. The elements of the new vector are the same (in the sense of eqv?) as the elements of the old.

mutable is a boolean argument. If it is set to #f, an immutable copy of vector will be created. The type of the second argument of vector-copy is used to disambiguate between the second and third version of the function. An exact integer will always be interpreted as start, a boolean value will always be interpreted as mutable.

(define a #(1 8 2 8))         ; a may be immutable
(define b (vector-copy a))    ; creates a mutable copy of a
(vector-set! b 0 3)           ; b is mutable
b  ⇒  #(3 8 2 8)
(define c (vector-copy a #f)) ; creates an immutable copy of a
(vector-set! c 0 3)  ⇒  error  ; error, since c is immutable
(define d (vector-copy b 1 3))
d  ⇒  #(8 2)

Returns a newly allocated mutable vector whose elements are the concatenation of the elements of the given vectors.

(vector-append #(a b c) #(d e f))  ⇒  #(a b c d e f)

Returns a newly allocated mutable vector whose elements are the concatenation of the elements of the vectors in xs. xs is a proper list of vectors.

(vector-concatenate '(#(a b c) #(d) #(e f)))  ⇒  #(a b c d e f)

Constructs a new mutable vector of the shortest size of the vector arguments vector1, vector2, etc. Each element at index i of the new vector is mapped from the old vectors by (f (vector-ref vector1 i) (vector-ref vector2 i) ...). The dynamic order of the application of f is unspecified.

(vector-map + #(1 2 3 4 5) #(10 20 30 40))  ⇒  #(11 22 33 44)

Constructs a new mutable vector of the shortest size of the vector arguments vector1, vector2, etc. Each element at index i of the new vector is mapped from the old vectors by (f i (vector-ref vector1 i) (vector-ref vector2 i) ...). The dynamic order of the application of f is unspecified.

(vector-map/index (lambda (i x y) (cons i (+ x y))) #(1 2 3) #(10 20 30))
⇒  #((0 . 11) (1 . 22) (2 . 33))

Procedure vector-sort returns a new vector containing the elements of vector in sorted order using pred as the "less than" predicate. If start and end are given, they indicate the sub-vector that should be sorted.

(vector-sort < (vector 7 4 9 1 2 8 5))
⇒  #(1 2 4 5 7 8 9)

Iterating over vectors

vector-for-each implements a simple vector iterator: it applies f to the corresponding list of parallel elements from vector1 vector2 ... in the range [0, length), where length is the length of the smallest vector argument passed. In contrast with vector-map, f is reliably applied to each subsequent element, starting at index 0, in the vectors.

(vector-for-each (lambda (x) (display x) (newline)) 
                 #("foo" "bar" "baz" "quux" "zot"))

foo
bar
baz
quux
zot

vector-for-each/index implements a simple vector iterator: it applies f to the index i and the corresponding list of parallel elements from vector1 vector2 ... in the range [0, length), where length is the length of the smallest vector argument passed. The only difference to vector-for-each is that vector-for-each/index always passes the current index as the first argument of f in addition to the elements from the vectors vector1 vector2 ....

(vector-for-each/index
  (lambda (i x) (display i)(display ": ")(display x)(newline))
  #("foo" "bar" "baz" "quux" "zot"))

0: foo
1: bar
2: baz
3: quux
4: zot

Managing vector state

Returns the number of elements in vector as an exact integer.

The vector-ref procedure returns the contents of element k of vector. It is an error if k is not a valid index of vector.

(vector-ref ’#(1 1 2 3 5 8 13 21) 5) ⇒  8
(vector-ref ’#(1 1 2 3 5 8 13 21) (exact (round (* 2 (acos -1)))))  ⇒  13

The vector-set! procedure stores obj in element k of vector. It is an error if k is not a valid index of vector.

(let ((vec (vector 0 '(2 2 2 2) "Anna")))
  (vector-set! vec 1 '("Sue" "Sue"))
  vec)
  ⇒  #(0 ("Sue" "Sue") "Anna")
(vector-set! '#(0 1 2) 1 "doe")
  ⇒  error    ;; constant/immutable vector

The vector-swap! procedure swaps the element j of vector with the element k of vector.

Destructive vector operations

Procedures which operate only on a part of a vector specify the applicable range in terms of an index interval [start; end[; i.e. the end index is always exclusive.

Copies the elements of vector from between start and end to vector to, starting at at. The order in which elements are copied is unspecified, except that if the source and destination overlap, copying takes place as if the source is first copied into a temporary vector and then into the destination. start defaults to 0 and end defaults to the length of vector.

It is an error if at is less than zero or greater than the length of to. It is also an error if (- (vector-length to) at) is less than (- end start).

(define a (vector 1 2 3 4 5))
(define b (vector 10 20 30 40 50)) (vector-copy! b 1 a 0 2)
b  ⇒  #(10 1 2 40 50)

The vector-fill! procedure stores fill in the elements of vector between start and end. start defaults to 0 and end defaults to the length of vector.

(define a (vector 1 2 3 4 5))
(vector-fill! a ’smash 2 4)
a  ⇒  #(1 2 smash smash 5)

Procedure vector-reverse! destructively reverses the contents of vector between start and end. start defaults to 0 and end defaults to the length of vector.

(define a (vector 1 2 3 4 5))
(vector-reverse! a)
a  ⇒  #(5 4 3 2 1)

Procedure vector-sort! destructively sorts the elements of vector using the "less than" predicate pred between the indices start and end. Default for start is 0, for end it is the length of the vector.

(define a (vector 7 4 9 1 2 8 5))
(vector-sort! < a)
a  ⇒  #(1 2 4 5 7 8 9)

Similar to vector-map which maps the various elements into a new vector via function f, procedure vector-map! destructively inserts the mapped elements into vector1. The dynamic order in which f gets applied to the elements is unspecified.

(define a (vector 1 2 3 4))
(vector-map! + a #(10 20 30))
a  ⇒  #(11 22 33 4)

Similar to vector-map/index which maps the various elements together with their index into a new vector via function f, procedure vector-map/index! destructively inserts the mapped elements into vector1. The dynamic order in which f gets applied to the elements is unspecified.

(define a (vector 1 2 3 4))
(vector-map/index! (lambda (i x y) (cons i (+ x y))) a #(10 20 30))
a  ⇒  #((0 . 11) (1 . 22) (2 . 33) 4)

Converting vectors

The vector->list procedure returns a newly allocated list of the objects contained in the elements of vector between start and end in the same order line in vector.

(vector->list ’#(dah dah didah))  ⇒  (dah dah didah)
(vector->list ’#(dah dah didah) 1 2)  ⇒  (dah)

The vector->string procedure returns a newly allocated string of the objects contained in the elements of vector between start and end. This procedure preserves the order of the characters. It is an error if any element of vector between start and end is not a character.

(vector->string #(#\1 #\2 #\3)  ⇒  "123"

Last updated