LISP - Accessing Characters of String
Lisp - Accessing Characters in a String
Section titled “Lisp - Accessing Characters in a String”In Common Lisp, a string is a one-dimensional array of characters. This structure allows for efficient, direct access to any character by its index. There are several standard functions to perform this access, each with subtle differences in usage and performance.
Key points to remember:
- Zero-Based Indexing: The first character is at index 0, the second at index 1, and so on.
- Character Type: The functions return a value of type
character, which Lisp prints using the#\notation (e.g.,#\A).
Core Accessor Functions
Section titled “Core Accessor Functions”| Function | Description | Best For |
|---|---|---|
char | The most general and recommended function. It works on any kind of string. | General purpose string access. |
schar | A specialized version of char that only works on simple-strings. It can be faster because it avoids checks required for more complex strings (e.g., those with fill pointers). | Performance-critical code where you know the string is a simple-string. |
aref | The generic array reference function. Since strings are arrays, it can be used to access characters. It is functionally equivalent to char for this purpose. | Generic code that operates on any type of array, not just strings. |
Example: Comparing char, schar, and aref
Section titled “Example: Comparing char, schar, and aref”The following example demonstrates how to use all three functions to access characters from a string. Note that for a standard string literal, their behavior is identical.
main.lisp
Section titled “main.lisp”;; Use defparameter for a global, dynamic variable (a common convention).(defparameter *my-string* "Modern Lisp")
(format t "Original String: ~s~%~%" *my-string*)
;; --- Accessing the first character (index 0) ---(format t "Using (char *my-string* 0): ~c~%" (char *my-string* 0))(format t "Using (schar *my-string* 0): ~c~%" (schar *my-string* 0))(format t "Using (aref *my-string* 0): ~c~%~%" (aref *my-string* 0))
;; --- Accessing the seventh character (index 6) ---(let ((index 6)) (format t "Accessing character at index ~d:~%" index) (format t "Character is: ~c~%" (char *my-string* index)))Output
Section titled “Output”Original String: "Modern Lisp"
Using (char *my-string* 0): MUsing (schar *my-string* 0): MUsing (aref *my-string* 0): M
Accessing character at index 6:Character is: LCommon Errors and Debugging Tips
Section titled “Common Errors and Debugging Tips”- Off-by-One Error: Forgetting that indexing starts at 0 is a common mistake. The last character of a string
sis at index(- (length s) 1). - Index Out of Bounds: Attempting to access an index equal to or greater than the string’s length will signal a runtime error. Always ensure your index is within the valid range
[0, length-1]. - Type Error with
schar: If you usescharon a complex string (e.g., one created with a fill pointer), atype-errorwill be signaled. Stick tocharunless you have a specific performance reason and have verified the string type.
;; Example of an out-of-bounds error(let ((my-string "Hi")) ;; This will cause an error because the valid indices are 0 and 1. (char my-string 2))Best Practices
Section titled “Best Practices”For clarity, robustness, and general-purpose code, prefer char. The potential performance gain from schar is often negligible in modern Lisp implementations unless you are operating inside a tight loop over millions of characters. Use aref when writing code that is designed to work with arrays in general, not just strings.