在 CASE 中引用 match 子句

Fra*_*ank 4 common-lisp

更新

我想我明白发生了什么事。Lisp 仅将'match 子句'(1 2 3)和 的部分'(41 42 43)视为键(因为它们都扩展为(Quote... 并且从这个角度来看,第三个代码片段中的第二个'= (QUOTE... 是一个“重复键”(而实际上它不是)根本没有键。这只是我的语法错误)。

我认为我的主要问题是我没有正确理解编译器警告。

原帖

我不理解case(或 sbcl)的以下行为。

这篇SO 帖子中,R. Joswig 指出,表单的 match 子句case不会被评估并被视为文字。因此匹配子句不应被引用。

我没有意识到这一点,引用了一个匹配条款,但忘记引用另一个。我不明白的是,为什么如果我引用一个匹配子句,编译器不会抱怨,但如果我引用两个匹配子句,编译器就会抱怨。具体来说:

> (let ((x 42))
     (case x
       ((1 2 3) 'first-branch)
       ('(41 42 43) 'second-branch)))      ; <=  second match clause quoted
NIL
Run Code Online (Sandbox Code Playgroud)

=> 无警告。

> (let ((x 42))
     (case x
       ('(1 2 3) 'first-branch)            ; <=  first match clause quoted
       ((41 42 43) 'second-branch)))
NIL
Run Code Online (Sandbox Code Playgroud)

=> 也没有警告。

> (let ((x 42))
     (case x
       ('(1 2 3) 'first-branch)            ; <=  both quoted
       ('(41 42 43) 'second-branch)))      ; <=  
NIL
Run Code Online (Sandbox Code Playgroud)

=>样式警告:

 ; caught STYLE-WARNING:
 ;  Duplicate key QUOTE in CASE form, occurring in the first clause:
 ;     ('(1 2 3) 'FIRST-BRANCH), and the second clause:
 ;     ('(41 42 43) 'SECOND-BRANCH).
Run Code Online (Sandbox Code Playgroud)

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

Rai*_*wig 5

只是为了澄清:这里的引号符号只是另一个符号,没有任何特定含义。Common Lisp 期望表达式子句的开头case是一个常量原子(如 )foo或常量原子列表(如 )(foo bar baz)。另请注意,Lisp 用作eql比较 - 因此,在数字和字符的情况下,它会比较身份或值,但不会比较内容。

此示例表明,这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
Run Code Online (Sandbox Code Playgroud)

如果我们写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
Run Code Online (Sandbox Code Playgroud)