Reputation: 209
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
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
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