#和#x27;与“:key”一起使用时,按照HyperSpec在公共Lisp工作中邻接?

#和#x27;与“:key”一起使用时,按照HyperSpec在公共Lisp工作中邻接?,lisp,common-lisp,ansi-common-lisp,Lisp,Common Lisp,Ansi Common Lisp,查看HyperSpec中的示例,我在示例部分看到以下内容: (setq slist '()) => NIL (setq slist (adjoin '(test-item 1) slist)) => ((TEST-ITEM 1)) (adjoin '(new-test-item 1) slist :key #'cadr) => ((TEST-ITEM 1)) 我本以为会发生以下情况: (adjoin '(new-test-item 1) slist :key #'cad

查看HyperSpec中的示例,我在示例部分看到以下内容:

(setq slist '()) =>  NIL
(setq slist (adjoin '(test-item 1) slist)) =>  ((TEST-ITEM 1))
(adjoin '(new-test-item 1) slist :key #'cadr) =>  ((TEST-ITEM 1))
我本以为会发生以下情况:

(adjoin '(new-test-item 1) slist :key #'cadr) =>  ((NEW-TEST-ITEM 1) (TEST-ITEM 1))
我的期望是由于以下文本:

当对每个元素迭代考虑对象O时 下一个图中列出的运算符F对序列S的Ei,它是 有时可用于控制O的存在方式 在S中测试由F测试。此控件基于 用:test或:test not参数指定的函数

此外:

对象O可能无法直接与Ei进行比较。如果a:关键参数 如果提供,则它是一个参数函数的指示符 将每个Ei作为参数调用,并生成一个对象Zi 用于比较。(如果没有:关键参数,则Zi为Ei。)

:key参数指定的函数永远不会在O上调用 它本身但是,如果功能在多个序列上运行(例如。, 与set difference中的情况一样,O将是调用 :在另一个序列的元素上设置键功能

因此,我们将slist(序列S)作为
”((测试项目1))
和O作为
”(新测试项目1)
。为了检查O是否应该邻接,将函数
#'cadr
应用于s的元素,第一个元素是
'(测试项目1)
。因此,该测试给出:

(cadr '(test-item 1)) => 1

现在,当O,
(新测试项1)
,与使用
#eql
#cadr
应用于S的E1的结果进行对比检查时(当没有提供
:test
时使用的相等函数),
false
结果应表示O是相邻的。至少我是这么想的。我误解了什么?

这是HyperSpec中的一个bug,已经在CLiki上写过了。有关部分包括:

问题描述: CLHS通过参考第17.2.1节,规定了存在:关键参数时的邻接行为 双参数测试。这是不正确的,因为第17.2.1节规定 键函数不是在ITEM参数上调用的,而是邻接的 按照pushnew中的规定。提案(附:澄清):

替换: test、test not和key影响如何确定项目 与列表的元素相同。有关详细信息,请参见第17.2.1节 (满足双参数测试)

作者:

项目是否已经是列表的成员由 使用:test或:test not进行比较。测试的第一个参数是:test 或:test not function是:key函数返回的结果(如果 提供),适用于该项目;第二个参数是 :key函数返回的列表(如果提供)。如果:关键是 提供时,用于从两个项目中提取待测试零件 和list元素

理论基础: 对邻接规范的澄清

现行做法: 所有实现都按照pushnew上的指定实现ADJOIN,而不是按照ADJOIN上的指定实现ADJOIN