Emacs Lisp:#s 不会每次都创建新的散列 table
Emacs Lisp: #s does not create a new hash table each time
我有以下功能:
(defun inc-map ()
(let ((ht #s(hash-table test contents-hash)))
(dolist (i (list 1 2 3 4))
(let ((old-val (or (gethash "foo" ht)
0)))
(puthash "foo" (+ 1 old-val) ht)))
ht))
尽管该函数似乎在本地定义了 ht
符号,但该函数似乎并不具有引用透明性。特别是,调用它一次 returns 哈希 table "foo" -> 4
,第二次调用它 returns "foo" -> 8
,第三次 return s "foo" -> 12
等等。
这里到底发生了什么,我如何将此函数更改为引用透明(并且每次 return "foo" -> 4
)?
这可能被认为是一个(轻微的)文档错误,因为它有点过于坚定地暗示使用印刷表示会创建一个 new 散列 table --一个容易被误解的声明。
但是,您会注意到文档说是 elisp reader 识别散列 table 的打印表示。
因此使用 #s
与调用 make-hash-table
不同。这里的区别相当于引用一个列表'(1 2 3)
和调用(list 1 2 3)
.
的区别
每种情况下的前者都由 reader 处理,因此可以看到相同的单个结果对象(分别为散列 table 或列表)在每次评估期间。
相反,在后一种情况下,reader 正在生成代码,在评估时,将创建一个新的散列 table 或列表;因此您在每次评估期间都会看到一个新对象。
我有以下功能:
(defun inc-map ()
(let ((ht #s(hash-table test contents-hash)))
(dolist (i (list 1 2 3 4))
(let ((old-val (or (gethash "foo" ht)
0)))
(puthash "foo" (+ 1 old-val) ht)))
ht))
尽管该函数似乎在本地定义了 ht
符号,但该函数似乎并不具有引用透明性。特别是,调用它一次 returns 哈希 table "foo" -> 4
,第二次调用它 returns "foo" -> 8
,第三次 return s "foo" -> 12
等等。
这里到底发生了什么,我如何将此函数更改为引用透明(并且每次 return "foo" -> 4
)?
这可能被认为是一个(轻微的)文档错误,因为它有点过于坚定地暗示使用印刷表示会创建一个 new 散列 table --一个容易被误解的声明。
但是,您会注意到文档说是 elisp reader 识别散列 table 的打印表示。
因此使用 #s
与调用 make-hash-table
不同。这里的区别相当于引用一个列表'(1 2 3)
和调用(list 1 2 3)
.
每种情况下的前者都由 reader 处理,因此可以看到相同的单个结果对象(分别为散列 table 或列表)在每次评估期间。
相反,在后一种情况下,reader 正在生成代码,在评估时,将创建一个新的散列 table 或列表;因此您在每次评估期间都会看到一个新对象。