user124577
user124577

Reputation: 209

Modifying hash-tables in Common Lisp and Let

I've been trying to modify a hash-table with the following code

(let ((alist '(gethash key *hash-table*)))
  (setf alist (cons 'key 'weight)))

but the problem is that it doesn't actually modify the hash-table (also note that

(let ((alist (gethash key *hash-table*)))
  (setf alist (cons 'key 'weight)))

doesn't work either, while the following code does work.

(setf (gethash key *hash-table*) (cons 'key 'weight)))

I can't understand why this works and the other one doesn't work. This is useful (outside of this code snippet) because (I assume) this is why I can't run a function like

(alist-initialize (gethash key *hash-table*))

with the definition being:

(defun alist-initialize (alist)
  (setf alist (cons 'a 'b))

Upvotes: 2

Views: 1046

Answers (2)

sds
sds

Reputation: 60004

Setting a variable modifies its local binding. You would not expect

(let ((a 5))
  (setf a 2))

to somehow change the value of 5 to 2. Similarly,

(let ((alist (gethash key *hash-table*))) 
  (setf alist (cons 'key 'weight)))

has no effect on (gethash key *hash-table*). What happens there is that key it looked up in *hash-table* and alist is bound to the value returned. Then setf modifies the binding of alist, being completely oblivious to the previous binding.

(note that your first form quotes the gethash call and thus does not access the hash table at all).

Your function should be defined like this:

(defun alist-initialize (key alist)
  (setf (gethash key *hash-table*) alist))

and called with two arguments, not one.

"In the interest of full disclosure", CL does provide facilities to go what you want (see symbol-macrolet and define-symbol-macro) but this is relatively advanced material which you should, IMO, ignore for now.

Upvotes: 10

Rainer Joswig
Rainer Joswig

Reputation: 139241

Why would you mix an assoc list and a hash-table? Both can be used for similar purposes, but they are independent of each other.

If you want to put something into a hash-table you have to write:

(setf (gethash key *hash-table*) value)

If you want to get the value:

(gethash key *hash-table*)

Upvotes: 1

Related Questions