修改Common Lisp和Let中的哈希表

use*_*577 2 lisp evaluation hashtable common-lisp

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

(let ((alist '(gethash key *hash-table*)))
  (setf alist (cons 'key 'weight)))
Run Code Online (Sandbox Code Playgroud)

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

(let ((alist (gethash key *hash-table*)))
  (setf alist (cons 'key 'weight)))
Run Code Online (Sandbox Code Playgroud)

也不起作用,而以下代码确实有效.

(setf (gethash key *hash-table*) (cons 'key 'weight)))
Run Code Online (Sandbox Code Playgroud)

我无法理解为什么这个有效而另一个无效.这很有用(在此代码片段之外)因为(我假设)这就是为什么我不能运行像这样的函数

(alist-initialize (gethash key *hash-table*))
Run Code Online (Sandbox Code Playgroud)

定义是:

(defun alist-initialize (alist)
  (setf alist (cons 'a 'b))
Run Code Online (Sandbox Code Playgroud)

sds*_*sds 9

设置变量会修改其本地绑定.你不会想到的

(let ((a 5))
  (setf a 2))
Run Code Online (Sandbox Code Playgroud)

以某种方式改变的价值52.同样的,

(let ((alist (gethash key *hash-table*))) 
  (setf alist (cons 'key 'weight)))
Run Code Online (Sandbox Code Playgroud)

对...没有影响(gethash key *hash-table*).key它会发生什么,它会查找*hash-table*alist返回返回的值.然后setf修改绑定alist,完全忘记先前的绑定.

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

你的函数应该像这样定义:

(defun alist-initialize (key alist)
  (setf (gethash key *hash-table*) alist))
Run Code Online (Sandbox Code Playgroud)

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

"为了充分披露",CL确实提供了你想要的设施(见symbol-macroletdefine-symbol-macro),但这是相对先进的材料,你现在应该忽略IMO.