How do I append a character to the end of a String

common-lisp

Solution

You've got the right diagnosis. It's not even a matter of literal data (e.g., `(list 1 2 3)` vs. `'(1 2 3)`) versus modifiable data, though. It's whether the vector has a fill pointer. The documentation for `vector-push` and `vector-push-extend` say that the vector argument is a vector with a fill pointer. You'll get a similar error with non-literal arrays that don't have a fill pointer, as in:

(let ((v (make-array 3)))
  (vector-push nil v))

All you need to do is make sure that you create the vector with a fill pointer, and that it big enough to hold the things you push in:

(let ((v (make-array 2 :fill-pointer 0)))
  (print v)
  (vector-push 'x v)
  (print v)
  (vector-push 'y v)
  (print v)
  (vector-push 'z v)
  (print v))

`vector-push` doesn't adjust the array, so you get not `z` in the vector from the final `vector-push`:

#() 
#(X) 
#(X Y) 
#(X Y) 

If you make the vector adjustable, and use `vector-push-extend`, you can get a bigger array:

(let ((v (make-array 2 :adjustable t :fill-pointer 0)))
  (print v)
  (vector-push 'x v)
  (print v)
  (vector-push 'y v)
  (print v)
  (vector-push-extend 'z v)
  (print v))

#() 
#(X) 
#(X Y) 
#(X Y Z) 

Using an element type of `character`, you'll be doing this with strings:

(let ((v (make-array 2 :element-type 'character :adjustable t :fill-pointer 0)))
  (print v)
  (vector-push #\x v)
  (print v)
  (vector-push #\y v)
  (print v)
  (vector-push-extend #\z v)
  (print v))

"" 
"x" 
"xy" 
"xyz" 

Problem

From my understanding Strings are vectors of type character. So far my attempts have been unfruitful ``` (vector-push #\a "Hol") ;; "Hol" Is not of type vector and simple-array ``` Is the literal "Hol" a constant vector in the same manner that '(1 2 3) is not the same as (list 1 2 3)? Should I just create a vector of characters explicitly and add characters to it?

Original source