【问题标题】:Emacs Lisp: #s does not create a new hash table each timeEmacs Lisp:#s 不会每次都创建新的哈希表
【发布时间】:2016-05-01 08:38:17
【问题描述】:

我有以下功能:

(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 符号,但该函数似乎不是引用透明的。特别是调用一次返回哈希表"foo" -> 4,第二次调用返回"foo" -> 8,第三次返回"foo" -> 12,以此类推。

这里到底发生了什么?如何将此函数更改为引用透明(并且每次都返回"foo" -> 4)?

【问题讨论】:

    标签: emacs elisp


    【解决方案1】:

    这可能被认为是一个(轻微的)文档错误,因为它有点过于坚定地表明使用打印的表示会创建一个 new 哈希表——这是一个容易被误解的声明。

    但是,您会注意到文档说是 elispreader 可以识别哈希表的打印表示。

    因此使用#s 与调用make-hash-table 不同。这里的区别相当于引用列表'(1 2 3)和调用(list 1 2 3)的区别。

    在每种情况下,前者都由 reader 处理,因此在每次评估期间都会看到相同的单个结果对象(分别是哈希表或列表)。

    相反,在后一种情况下,阅读器生成的代码在评估时将创建一个新的哈希表或列表;因此,您在每次评估期间都会看到一个新对象。

    【讨论】:

    • 是否可以修改'(1 2 3),使其实际上返回列表,而不是/不仅仅是1 2 3
    • user1034749:我不确定我是否理解这个问题。任何 X 的 'X(quote X) 的简写。 X 可以是 elisp 阅读器可以理解的任何形式,它会评估阅读器创建的对象。见C-h f quote
    • 您在#s'(1 2 3) 之间进行类比,有问题的#s(something)#s(something) 可以给出不同的结果,那么是否有可能多次评估'(1 2 3) 得到不同的结果?第一次喜欢'(1 2 3),下次喜欢'(1 2 3 4)
    • 如果是同一个对象,那么肯定是的。 lisp reader 读取'(1 2 3) 并创建一个包含这三个成员的列表对象。在评估期间,其他代码可以以任何方式操作该列表对象。 最初读取的代码是'(1 2 3)这一事实并不意味着关联的 lisp 对象的结构必须继续来表示该原始文本形式。 emacs.stackexchange.com/questions/20535/… 就是一个很好的例子。
    • 大概,通过 doc,您的意思是 Elisp 手册,节点 Creating Hash。上面写着“你也可以使用#s 创建一个新的哈希表”,我同意这是误导性的。我刚刚为此提交了bug #23417
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-23
    • 1970-01-01
    • 2018-10-05
    • 2020-07-18
    • 1970-01-01
    • 1970-01-01
    • 2014-04-25
    相关资源
    最近更新 更多