LISP - Accessing Elements of Vectors
Lisp - Accessing Vector Elements
Section titled “Lisp - Accessing Vector Elements”In Common Lisp, a vector is a one-dimensional array. As a fundamental data structure, knowing how to efficiently access its elements is a core skill. This tutorial covers the modern, idiomatic ways to retrieve elements from a vector.
The Universal Accessor: aref
Section titled “The Universal Accessor: aref”The function aref (short for array reference) is the standard, general-purpose function for accessing elements of any array, including vectors. It is the most common and recommended way to access vector elements in modern Lisp code.
main.lisp
Section titled “main.lisp”;; Define a vector using the 'vector' constructor for simplicity.(let ((my-vector (vector 10 20 30 40 50)))
;; Access and print the first element (at index 0). ;; Lisp vectors, like most arrays in programming, are zero-indexed. (format t "First element: ~a~%" (aref my-vector 0))
;; Access and print the fourth element (at index 3). (format t "Fourth element: ~a~%" (aref my-vector 3)))Output
Section titled “Output”First element: 10Fourth element: 40Specialized Accessors for Performance
Section titled “Specialized Accessors for Performance”While aref is universal, Common Lisp provides specialized functions for specific vector types that can offer better performance in compiled code.
For Simple Vectors: svref
Section titled “For Simple Vectors: svref”A simple vector is a vector that is not displaced, has no fill pointer, and is not adjustable. If you are certain you are working with a simple vector (which is often the case), svref (simple vector reference) can be more efficient than aref because the compiler doesn’t need to check for these special features.
main.lisp
Section titled “main.lisp”;; The (vector ...) constructor creates a simple vector.(let ((simple-vec (vector "apple" "banana" "cherry")))
;; Using svref is efficient here. (format t "Element at index 2: ~s~%" (svref simple-vec 2)))Output
Section titled “Output”Element at index 2: "cherry"The Generic Sequence Accessor: elt
Section titled “The Generic Sequence Accessor: elt”The elt function is a generic accessor for any sequence type, which includes lists, vectors, and strings. You can use elt on a vector, and it will behave just like aref. Its main advantage is in writing functions that can operate on different kinds of sequences without changing the code.
main.lisp
Section titled “main.lisp”;; A function that gets the second element of any sequence.(defun get-second-element (sequence) (when (>= (length sequence) 2) (elt sequence 1)))
(let ((my-vector #(100 200 300)) (my-list '(a b c)))
(format t "Second element of vector: ~a~%" (get-second-element my-vector)) (format t "Second element of list: ~a~%" (get-second-element my-list)))Output
Section titled “Output”Second element of vector: 200Second element of list: BBest Practices and Common Errors
Section titled “Best Practices and Common Errors”- Default to
aref: For general-purpose vector access,arefis the clear choice. It’s readable, universal for all arrays, and modern Lisp compilers are excellent at optimizing it. - Use
svreffor Optimization: Only switch tosvrefif you are in a performance-critical section of your code and you have profiled it to know that array access is a bottleneck. - Use
eltfor Genericity: Useeltwhen writing functions that need to be polymorphic over different sequence types. - Error: Out-of-Bounds Index: Accessing an index that is negative or greater than or equal to the vector’s length will signal an error. Always ensure your index is within the valid range
[0, (length vector) - 1]. - Debugging Tip: If you get an unexpected out-of-bounds error, use
(format t "Accessing vector ~s at index ~d~%" my-vector index)right before thearefcall to inspect the values that are causing the problem.