我想我明白发生了什么。 Lisp只使用匹配子句'
和'(1 2 3)
的{{1}}部分作为关键字(因为它们都扩展为'(41 42 43)
...并且从这个角度来看第二个{{ 1}} = (Quote
...在第三个代码段中是一个“重复键”(实际上它根本不是一个键。这只是我的语法错误)。
我认为我的主要问题是我没有正确理解编译器警告。
我不理解'
(或sbcl)的以下行为。
在this SO帖子中,R. Joswig指出(QUOTE
表单的匹配子句不会被评估并视为文字。因此不应引用匹配条款。
没有意识到这一点,我引用了一个匹配条款,但忘了引用另一个。我不明白的是,如果我引用一个匹配条款,为什么编译器不会抱怨,但如果我引用它们两个就会抱怨。具体做法是:
case
=>没有警告。
case
=>也没有警告。
> (let ((x 42))
(case x
((1 2 3) 'first-branch)
('(41 42 43) 'second-branch))) ; <= second match clause quoted
NIL
=&GT; 样式警告:
> (let ((x 42))
(case x
('(1 2 3) 'first-branch) ; <= first match clause quoted
((41 42 43) 'second-branch)))
NIL
为什么编译器只在引用两个匹配子句时才会抱怨,但如果我只引用一个匹配子句则不会抱怨?
答案 0 :(得分:3)
只是为了说清楚:引号符号在这里只是另一个没有任何特定含义的符号。 Common Lisp在foo
表达式的子句的开头期望要么是(foo bar baz)
之类的常量原子,要么是eql
之类的常量原子列表。另请注意,Lisp使用quote
作为比较 - 因此它在数字和字符的情况下比较身份或值,但不对内容进行比较。
此示例显示case
只是CL-USER> (case 2
((quote foo) 'foo)
((quote bar) 'bar))
WARNING: Duplicate key QUOTE in CASE form, occurring in the first clause:
('FOO 'FOO), and the second clause:
('BAR 'BAR).
NIL
子句中的另一个符号:
baz
如果我们写quote
而不是CL-USER> (case 2
((baz foo) 'foo)
((baz bar) 'bar))
WARNING: Duplicate key BAZ in CASE form, occurring in the first clause:
((BAZ FOO) 'FOO), and the second clause:
((BAZ BAR) 'BAR).
NIL
,我们会收到相同的警告:
{{1}}
答案 1 :(得分:2)
由于未评估case
,因此当您quote
两种情况时,代码等同于:
(let ((x 2 ))
(case x
((QUOTE (1 2 3)) 'first-branch)
((QUOTE (41 42 43)) 'second-branch)))
表示您在两种形式中都有文字QUOTE
,这会导致出现警告信息。