Skip to content

LISP - String Case Conversion

Common Lisp provides a standard set of functions for converting the case of characters within a string. These functions come in two main flavors: constructive (non-destructive) and destructive.

These functions return a new string with the converted case, leaving the original string unmodified. This is the safer and more common approach.

FunctionDescription
string-upcaseReturns a new string with all alphabetic characters converted to uppercase.
string-downcaseReturns a new string with all alphabetic characters converted to lowercase.
string-capitalizeReturns a new string with the first letter of each word capitalized.

These functions modify the original string in place. They are typically named with a leading n (for ‘non-consing’). Use them with caution, as they can lead to unexpected behavior if the string is shared elsewhere in your program. They are primarily used for performance optimization in critical code paths.

FunctionDescription
nstring-upcaseModifies the string, converting all alphabetic characters to uppercase.
nstring-downcaseModifies the string, converting all alphabetic characters to lowercase.
nstring-capitalizeModifies the string, capitalizing the first letter of each word.

Create a file main.lisp to see how non-destructive functions work.

;;; main.lisp - Demonstrating string case conversion
(let ((original-string "a big HELLO from tutorials point"))
(format t "Original: ~s~%" original-string)
;; Constructive functions create new strings
(let ((lower (string-downcase original-string))
(upper (string-upcase original-string))
(capital (string-capitalize original-string)))
(format t "Downcased: ~s~%" lower)
(format t "Upcased: ~s~%" upper)
(format t "Capitalized: ~s~%" capital))
;; The original string remains unchanged
(format t "After Ops: ~s~%" original-string))

Executing this code produces:

Original: "a big HELLO from tutorials point"
Downcased: "a big hello from tutorials point"
Upcased: "A BIG HELLO FROM TUTORIALS POINT"
Capitalized: "A Big Hello From Tutorials Point"
After Ops: "a big HELLO from tutorials point"

Specifying Subsequences with :start and :end

Section titled “Specifying Subsequences with :start and :end”

All these functions accept optional :start and :end keyword arguments to operate on only a portion of the string. The indices are zero-based.

(let ((my-string "a big hello from tutorials point"))
(format t "~%Original: ~s~%" my-string)
;; Upercase only the word "hello" (from index 6 to 11)
(let ((partial-upper (string-upcase my-string :start 6 :end 11)))
(format t "Partially Up: ~s~%" partial-upper)))

This part of the code would output:

Original: "a big hello from tutorials point"
Partially Up: "a big HELLO from tutorials point"
  • Prefer Non-Destructive: As a rule of thumb, always use the non-destructive versions (string-upcase, etc.) unless you have a measured performance bottleneck and you are certain the original string data is not used elsewhere. Functional purity makes code easier to reason about.
  • Keyword Arguments: The :start and :end keyword arguments are a common pattern across all sequence functions in Common Lisp (e.g., for lists, vectors, and strings). Mastering them provides a consistent way to manipulate subsequences.
  • Unicode and Character Sets: Modern Common Lisp implementations are generally Unicode-aware. Case conversion functions work correctly for a wide range of international characters, not just ASCII.