Skip to content

Updating Values of Hash Table

Hash tables are a fundamental and highly efficient data structure in Common Lisp for storing key-value pairs. This tutorial covers the standard way to add, update, and manage entries in a hash table.

The primary mechanism for adding or updating a value in a hash table is the combination of (setf gethash).

  • (make-hash-table): Creates a new, empty hash table.
  • (gethash key table): Retrieves the value associated with key from the table. If the key is not found, it returns nil.
  • (setf (gethash key table) value): This powerful construct sets the value associated with key to value. If key already exists, its value is updated. If key does not exist, a new entry is created.

When you create a hash table, you can specify how keys are compared using the :test argument. This is crucial for correct behavior.

  • #'eql (default): Compares if two objects are the same. Ideal for symbols and numbers. (eql 'a 'a) is true, but (eql "a" "a") is false because they are two different string objects in memory.
  • #'equal: Compares if two objects have the same structure and contents. This is necessary for string keys.
  • #'eq: Like eql but may not work for numbers. Compares memory location.
  • #'equalp: A more lenient version of equal that ignores case in strings and numeric types.

Example 1: Using Default eql Test (for Symbols)

Section titled “Example 1: Using Default eql Test (for Symbols)”

This example shows adding and updating a hash table using symbols as keys, which works perfectly with the default eql test.

;; Create a hash table with the default test ('eql').
(defvar *symbol-ages* (make-hash-table))
;; Add initial key-value pairs.
(setf (gethash 'alice *symbol-ages*) 30)
(setf (gethash 'bob *symbol-ages*) 45)
(format t "Initial age of Alice: ~a~%" (gethash 'alice *symbol-ages*))
;; Update an existing value.
(format t "Updating Alice's age to 31...~%")
(setf (gethash 'alice *symbol-ages*) 31)
(format t "Updated age of Alice: ~a~%" (gethash 'alice *symbol-ages*))
;; Add a new entry.
(format t "Adding Charlie, age 25...~%")
(setf (gethash 'charlie *symbol-ages*) 25)
(format t "Age of Charlie: ~a~%" (gethash 'charlie *symbol-ages*))
Initial age of Alice: 30
Updating Alice's age to 31...
Updated age of Alice: 31
Adding Charlie, age 25...
Age of Charlie: 25

Example 2: Using equal Test for String Keys

Section titled “Example 2: Using equal Test for String Keys”

When using strings as keys, you must specify #'equal as the test function.

;; Create a hash table with the 'equal' test for strings.
(defvar *fruit-prices* (make-hash-table :test #'equal))
;; Add key-value pairs.
(setf (gethash "apple" *fruit-prices*) 1.50)
(setf (gethash "banana" *fruit-prices*) 0.75)
(format t "Initial price of an apple: $~,2f~%" (gethash "apple" *fruit-prices*))
;; Update the price of an apple.
(setf (gethash "apple" *fruit-prices*) 1.75)
(format t "Updated price of an apple: $~,2f~%" (gethash "apple" *fruit-prices*))
Initial price of an apple: $1.50
Updated price of an apple: $1.75

To remove an entry from a hash table, use the remhash function. It returns t if an entry was removed, and nil otherwise.

(remhash 'bob *symbol-ages*) ; => T (entry removed)
(gethash 'bob *symbol-ages*) ; => NIL (no longer exists)
(remhash 'dave *symbol-ages*) ; => NIL (was never there)