我用
: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))
这个问题已经解决了吗?我正在努力解决同样的问题(相等运算符在作为函数调用时与用作哈希表的 :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”中?或者在哪里?请帮助最终彻底解决这个问题!