案例

时间:2017-04-04 14:42:39

标签: common-lisp

更新

我想我明白发生了什么。 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

为什么编译器只在引用两个匹配子句时才会抱怨,但如果我只引用一个匹配子句则不会抱怨?

2 个答案:

答案 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,这会导致出现警告信息。