# 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

(vector? obj) [procedure]

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

(mutable-vector? obj) [procedure]

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

(immutable-vector? obj) [procedure]

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

(vector= eql vector …) [procedure]

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

(make-vector k) [procedure]
(make-vector k fill)

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.

(vector obj …) [procedure]

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

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

(immutable-vector obj …) [procedure]

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

(list->vector list) [procedure]

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)

(list->immutable-vector list) [procedure]

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

(string->vector str) [procedure]
(string->vector str start)
(string->vector str start end)

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)

(vector-copy vector) [procedure]
(vector-copy vector mutable)
(vector-copy vector start)
(vector-copy vector start end)
(vector-copy vector start end mutable)

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)

(vector-append vector …) [procedure]

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)

(vector-concatenate vector xs) [procedure]

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)

(vector-map f vector1 vector2 …) [procedure]

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)

(vector-map/index f vector1 vector2 …) [procedure]

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))

(vector-sort pred vector) [procedure]
(vector-sort pred vector start)
(vector-sort pred vector start end)

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)

## Managing vector state

(vector-length vector) [procedure]

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

(vector-ref vector k) [procedure]

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

(vector-set! vector k obj) [procedure]

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

(vector-swap! vector j k) [procedure]

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.

(vector-copy! to at from) [procedure]
(vector-copy! to at from start)
(vector-copy! to at from start end)

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)

(vector-fill! vector fill) [procedure]
(vector-fill! vector fill start)
(vector-fill! vector fill start end)

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)

(vector-reverse! vector) [procedure]
(vector-reverse! vector start)
(vector-reverse! vector start end)

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)

(vector-sort! pred vector) [procedure]
(vector-sort! pred vector start)
(vector-sort! pred vector start end)

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)

(vector-map! f vector1 vector2 …) [procedure]

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)

(vector-map/index! f vector1 vector2 …) [procedure]

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)

## Iterating over vectors

(vector-for-each f vector1 vector2 …) [procedure]

`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 f vector1 vector2 …) [procedure]

`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

## Converting vectors

(vector->list vector) [procedure]
(vector->list vector start)
(vector->list vector start end)

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)

(vector->string vector) [procedure]
(vector->string vector start)
(vector->string vector start end)

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"