在Common Lisp和Let中修改哈希表



我一直在尝试用以下代码修改哈希表

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

但问题是它实际上并没有修改哈希表(也要注意

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

也不起作用,而下面的代码起作用。

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

我不明白为什么这个有效,另一个无效。这很有用(在这个代码片段之外),因为(我想)这就是为什么我不能运行这样的函数

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

定义为:

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

设置变量会修改其本地绑定。你不会期望

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

以某种方式将CCD_ 1的值改变为CCD_。类似地,

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

对CCD_ 3无影响。发生的情况是它在*hash-table*alist中查找的key与返回的值绑定。然后setf修改了alist的绑定,完全忽略了之前的绑定。

(请注意,您的第一个表单引用了gethash调用,因此根本不访问哈希表)。

你的功能应该这样定义:

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

并用两个参数调用,而不是用一个

"为了充分公开";,CL确实提供了你想去的地方的设施(见50和define-symbol-macro),但这是一种相对先进的材料,IMO现在应该忽略它。

为什么要混合使用assoc列表和哈希表?两者可以用于类似的目的,但它们彼此独立。

如果你想把一些东西放进哈希表,你必须写:

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

如果你想获得价值:

(gethash key *hash-table*)

最新更新