Lisp 哈希表相等性测试

问题描述 投票:0回答:1

我用

:test #'equalp
制作了一个哈希表。我的钥匙就是这种类型的结构

#S(KEY
        :WMES (#S(WME
                  :TYPE BLOCK
                  :NAME B1
                  :ABS-POS ((^LEFT 0) (^RIGHT 20) (^BOTTOM 0) (^TOP 5))
                  :TIME-STAMP 0)
               #S(WME
                  :TYPE BLOCK
                  :NAME B2
                  :ABS-POS ((^LEFT 15) (^RIGHT 20) (^BOTTOM 5) (^TOP 10))
                  :TIME-STAMP 0)
               #S(WME
                  :TYPE GRIPPER
                  :NAME G1
                  :ABS-POS ((^X 10) (^Y 100))
                  :TIME-STAMP 0))
        :GOALS (DUMMY-GOAL)
        :ACTIONS (DUMMY-ACTION))

当我这样做时

(equalp <key1> <key2>)
如果两个键结构相同且内容相同,则函数返回 true。

相反,当我使用

(gethash <key> *my-hash*)
检查哈希表中的某个键时,即使存在与该键关联的值,该函数也会返回
nil nil
。谁能解释为什么
(equalp <key1> <key2>)
:test #'equalp
返回不同的结果?

我的 Lisp 实现是 SBCL,我在 emacs 中使用 slime。

我很感谢您的帮助。

编辑

这是结构定义

(defstruct key
  (wmes '() :type list)
  (goals '() :type list)
  (actions '() :type list))

(defstruct wme
  (type '() :type symbol)
  (name '() :type symbol)
  (abs-pos '() :type list)
  (time-stamp 0 :type integer))
lisp hashtable common-lisp sbcl
1个回答
0
投票

这个问题已经解决了吗?我正在努力解决同样的问题(相等运算符在作为函数调用时与用作哈希表的 :test 时似乎评估不同)。我提供了一个 MWE 供其他人在这里复制(用 LW Professional 8 编码):

让我们定义一个结构

(defstruct teststruct
  (numberlist nil :type list)
  )

让我们定义一个相等运算符

(defun struct-equal (struct1 struct2)
  (flet ((remainder (numberlist) (mapcar #'(lambda (x) (rem x 1000)) numberlist)))
    (and (equalp (print (sort (remainder (teststruct-numberlist struct1)) '<)) 
                 (print (sort (remainder (teststruct-numberlist struct2)) '<))))
    )
  )

测试:

(let ((struct1 (make-teststruct :numberlist '(500 1300 700 900)))
      (struct2 (make-teststruct :numberlist '(1500 2300 3700 2900))))
  (struct-equal struct1 struct2)
  )

=> t ...正如预期的那样

(let ((struct1 (make-teststruct :numberlist '(500 1300 700 900)))
      (struct2 (make-teststruct :numberlist '(1500 2100 3700 2900))))
  (struct-equal struct1 struct2)
  )

=> 无...正如预期的那样


现在让我们编写一个函数来生成哈希表并使用唯一数据填充哈希表(基于相等运算符)

(defun write-hash-keys (data &optional (test 'equalp))
  (let ((hashtable (make-hash-table :test (print test)))
        (index 0))
    ; populate the hashtable
    (loop for item in data unless (gethash item hashtable) ; check if key exists in table
            do (setf (gethash item hashtable) (incf index))) ; write data as key, incremental index as value
    ; lookup keys in hashtable and output values as list
    (list (loop for item in data collect (gethash item hashtable)) ; output indices (values)
          hashtable)
    ))

现在让我们用这个函数测试相等运算符

(let ((struct1 (make-teststruct :numberlist '(500 1300 700 900)))
      (struct2 (make-teststruct :numberlist '(1500 2300 3700 2900))))
  (describe (second (write-hash-keys (list struct1 struct2 struct1) 'struct-equal)))
  )



   =>  (300 500 700 900)
   =>  (300 500 700 900)


; #<struct-equal Hash Table{2} 8010161213> is a hash-table
; #S(teststruct :numberlist (1500 2300 3700 2900))      2
; #S(teststruct :numberlist (500 1300 700 900))         1

哈希表包含两个条目,其结构的相等性先前评估为 t。所以 struct-equal 与 gethash 一起使用时计算结果为 nil??????

(let ((struct1 (make-teststruct :numberlist '(500 1300 700 900)))
      (struct2 (make-teststruct :numberlist '(500 1300 700 900))))
  (describe (second (write-hash-keys (list struct1 struct2 struct1) 'struct-equal)))
  )


; #<struct-equal Hash Table{1} 801004F4BB> is a hash-table
; #S(teststruct :numberlist (500 1300 700 900))     1

哈希表包含单个条目。因此,struct-equal 的计算结果为 t?我不明白这种差异。错误是在“剩余”flet 语句中吗?或者在“gethash”中?或者在哪里?请帮助最终彻底解决这个问题!

© www.soinside.com 2019 - 2024. All rights reserved.