Common lisp 为什么在case/ecase中不能匹配nil?
以下表格Common lisp 为什么在case/ecase中不能匹配nil?,common-lisp,sbcl,Common Lisp,Sbcl,以下表格 (let ((foo nil)) (ecase foo (:bar 1) (:baz 2) (nil 3))) 通过ECASE表达式抛出错误NIL。解决方法似乎是用括号将nil大小写括起来,如下所示: (let ((foo nil)) (ecase foo (:bar 1) (:baz 2) ((nil) 3))) ;; => 3 但是为什么第一个例子不起作用呢?未包装的nil大小写是否有特殊含义?大小写中的每个子句可以
(let ((foo nil))
(ecase foo
(:bar 1)
(:baz 2)
(nil 3)))
通过ECASE表达式抛出错误NIL。解决方法似乎是用括号将nil
大小写括起来,如下所示:
(let ((foo nil))
(ecase foo
(:bar 1)
(:baz 2)
((nil) 3))) ;; => 3
但是为什么第一个例子不起作用呢?未包装的nil
大小写是否有特殊含义?大小写中的每个子句可以与单个项目或项目列表匹配,例如,您可以编写:
(ecase foo
(:bar 1) ;; match a specific symbol
((:baz :quux) 2)) ;; match either of these symbols
NIL
也是Lisp中的空列表,当它在case
中用作测试时,这就是它的处理方式,因此它从不匹配任何内容。类似地,T
和否则
用于指定默认情况,因此不能将它们作为单个项目进行匹配。要匹配其中任何一个,您需要将它们放在列表中
更严格地说,在一个条款中提到了关于键的内容:
键---对象列表的指示符。在这种情况下,符号t
和否则
不能用作钥匙指示器。要将这些符号本身称为键,必须分别使用指示符(t)
和(否则)
a的定义是:
对象列表的指示符;也就是说,一个表示列表的对象是:一个非nil原子(表示元素为该非nil原子的单态列表)或一个适当的列表(表示自身)
请注意,将单个原子视为单原子列表的情况表示为“non-nil atom”。这允许NIL
落入第二种情况,其中一个适当的列表表示它自己。否则,将无法为空列表创建列表指示符,因为NIL
将表示(NIL)
您可能会争辩说,在CASE
中有一个空的键列表没有多大意义,因为它永远不会匹配任何东西,整个子句可以省略。这种退化情况有利于自动代码生成(例如,扩展为案例
的其他宏),因为它们可能会生成空列表,并且应与其他列表一致处理。对他们来说,要使子句的生成以是否有键为条件会更加困难。您也可以使用'nil
@Gwang JinKim,但是,您也可以匹配quote
,因为'nil
是(quote nil)
的读取器语法,在案例的上下文中,这意味着匹配quote
或nil
@coredump谢谢-真-我试过:(let((foo'quote))(案例foo(bar 1)(baz 2)(quote'upps)('nil 3));;返回UPPS
,因此对于nil
的情况,只有(nil)
才能正确匹配。@Gwang JinKim:不计算案例项,因此引用它们毫无意义。不要在案例中使用引号。这完全有道理。谢谢你的解释!