Skip to content

LISP - Modifications to Vectors

In Common Lisp, a vector is a one-dimensional array that can hold elements of any type. Vectors are a fundamental and efficient data structure for managing ordered collections. This tutorial covers the modern, standard way to create, access, and modify vectors, focusing on best practices for today’s Lisp development.

Creating and Modifying Vectors with vector, aref, and setf

Section titled “Creating and Modifying Vectors with vector, aref, and setf”

The most common and general-purpose tools for vector manipulation are:

  • vector: A function to create a new simple vector with specified elements.
  • aref: The Array REFerence function, used to access an element at a specific index.
  • setf: The universal assignment macro, used with aref to modify an element at a specific index.

While you might see svref (Simple Vector Reference) in older code, aref is the more general and recommended function as it works on all array types, including vectors. Modern Lisp compilers are highly optimized and will often produce equally efficient code for aref on simple vectors.

(defun vector-modification-example ()
"Demonstrates creating, accessing, and modifying a vector."
;; 1. Create a vector using the `vector` function.
;; Best practice is to use `let` to create local variables.
(let ((my-vector (vector 'a 'b 'c 'd)))
;; 2. Print the original vector.
;; `format` is more flexible than `print`.
;; ~a is for aesthetic output, ~s is for Lisp-readable output.
(format t "Original vector: ~s~%" my-vector)
;; 3. Modify the element at index 1 (the second element).
;; Lisp uses zero-based indexing.
(setf (aref my-vector 1) 'z)
;; 4. Print the updated vector to show the change.
(format t "Modified vector: ~s~%" my-vector)))
;; Run the example function
(vector-modification-example)

When you compile and run this code in a modern Lisp environment, you will see:

Original vector: #(A B C D)
Modified vector: #(A Z C D)
  • Zero-Based Indexing: Remember that the first element of a vector is at index 0, the second at index 1, and so on. The last element is at index (- (length vector) 1).
  • Error Handling: Accessing an index outside the vector’s bounds (e.g., index 4 in a 4-element vector) will signal a control-error. In a real application, you should validate indices or handle errors using handler-case.
  • General vs. Simple Vectors: (vector ...) creates a simple vector, which is fixed in size. You can also create adjustable vectors with fill pointers using make-array. For most use cases, simple vectors are sufficient and efficient.
  • Modern Development Workflow: For serious Lisp development, use a modern setup like SBCL (a high-performance compiler), Quicklisp (a package manager), and ASDF (a build system). An interactive editor like Emacs with SLIME/SLY or VS Code with Alive provides a powerful REPL-driven development experience.

If you are unsure about the state or type of a vector in your program, use the inspect function in your REPL. For example, (inspect my-vector) will open an interactive inspector that shows you the vector’s type, length, and contents, which is invaluable for debugging.