关于案件的问题

Gol*_*den 2 lisp common-lisp

我试图创建一个示例cond,case并提出了一个简单的fizz buzz问题实现(详见维基百科).

我的初始版本是:

(defun is-fizz-buzz (n)
  (cond ((and (zerop (mod n 3)) (zerop (mod n 5))) 'fizz-buzz)
        ((zerop (mod n 3)) 'fizz)
        ((zerop (mod n 5)) 'buzz)
        (t n)))

(defun fizz-buzz (n)
  (princ (case (is-fizz-buzz n)
               ('fizz "Fizz!")
               ('buzz "Buzz!")
               ('fizz-buzz "Fizz-Buzz!")
               (otherwise n))))
Run Code Online (Sandbox Code Playgroud)

现在,@ RainerJoswig向我指出我case的错.我很惊讶,因为它,因为它应该工作过,但他的方式更有经验和Lisp比我,他最可能是正确的(事实上,他是).

我试着阅读并理解http://clhs.lisp.se/Body/m_case_.htm,但现在我留下的问题多于答案.因为我不想讨论140个字符的内容,因为它可能对其他Lisp初学者有帮助,我想在这里发表我的问题.

基本上,语法case被描述为

case keyform {normal-clause}* [otherwise-clause] => result*
Run Code Online (Sandbox Code Playgroud)

keyform很容易:它是一个被评估的表单,用于获取正在测试的密钥.当然

(is-fizz-buzz n)
Run Code Online (Sandbox Code Playgroud)

是一个形式,它返回一个符号,因此一切都很好.另外,正如我从Land of Lisp中学到的那样,case内部使用eq,并且eq用于比较符号,这也应该没问题.

现在,normal-clause:这被定义为

(keys form*)
Run Code Online (Sandbox Code Playgroud)

form*再简单,它只是一些形式,基本上是隐含的progn.因为keys,它告诉我这是一个对象列表的指示符.唷.我的问题在这里开始......

这份文件告诉我一个指示符是:

表示另一个对象的对象.

嗯.正如case工作一样eq,我本以为我需要在这里给出一个符号.为什么是keys一个对象列表的指示符,而不是一个对象?我可以在一个分支中使用多个符号进行比较吗?我想这里的问题归结为没有真正理解a的意思designator,但也许有人可以帮助我并推动我走向正确的方向.你如何解释Lisp中的指示符是什么?

然后,我开始玩代码,我注意到如果我删除'字符,事情仍然有效.代码

(defun fizz-buzz (n)
  (princ (case (is-fizz-buzz n)
               (fizz "Fizz!")
               (buzz "Buzz!")
               (fizz-buzz "Fizz-Buzz!")
               (otherwise n))))
Run Code Online (Sandbox Code Playgroud)

产生与上面代码完全相同的结果.为什么是这样?我甚至都不希望这是可执行的,因为(fizz "Fizz!")我看起来像一个函数调用fizz,它不存在.为什么这样做?

然后,最后一个问题是,当我跑步时

(case 'quote ('foo 1) ('bar 2))
Run Code Online (Sandbox Code Playgroud)

它返回1(这似乎不符合逻辑,我原以为nil).如果我改成这个

(case 'quote ('foo 1) ('bar 2) (otherwise 3))
Run Code Online (Sandbox Code Playgroud)

它仍然会回归1,而3不像我现在所期望的那样.从文档中我不明白为什么我的否则条款显然不应该做什么.

任何提示,为什么这两个案件表现得像他们一样?

Rai*_*wig 5

CASE使用EQLEQ.EQL在大多数情况下是默认比较.因此案例适用于身份,数字和字符.

不评估关键字.引用对象是没有意义的.引用意味着停止评估.但没有评价 - >没有报价.

键形式可以是单个项目,也可以是项目列表

(case foo
  (bar 'it-is-bar)
  ((1 2) 'one-or-two)
  (1     'one))
  ((apple banana orange) 'either-apple-banana-or-orange)))
Run Code Online (Sandbox Code Playgroud)

它还意味着左侧是常量,没有变量.bar上面是符号bar,而不是变量bar.

问题:

 (case 'quote
   ('foo 'foo-or-quote))
Run Code Online (Sandbox Code Playgroud)

因为它确实是

 (case 'quote
   ((quote foo) 'foo-or-quote))
Run Code Online (Sandbox Code Playgroud)