【发布时间】:2014-06-05 13:17:17
【问题描述】:
我尝试为 cond 和 case 创建一个示例,并提出了 fizz buzz 问题的简单实现(有关详细信息,请参阅 Wikipedia)。
我的初始版本是:
(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))))
现在,@RainerJoswig 向我指出我的case 是错误的。我很惊讶,因为它应该起作用了,但是由于他在 Lisp 方面的经验比我方式多,他很可能是对的(事实上,他是)。
我试图阅读和理解http://clhs.lisp.se/Body/m_case_.htm,但现在我的问题多于答案。由于我不想讨论 140 个字符的内容,而且它可能对其他 Lisp 初学者有所帮助,所以我想在这里发布我的问题。
基本上case的语法描述为
case keyform {normal-clause}* [otherwise-clause] => result*
keyform 很简单:它是一种经过评估以获取正在测试的密钥的表单。肯定的
(is-fizz-buzz n)
是一种形式,它返回一个符号,因此一切看起来都很好。此外,正如我从 Land of Lisp 中了解到的,case 在内部与 eq 一起使用,并且由于 eq 用于比较符号,这也应该没问题。
现在,normal-clause:这被定义为
(keys form*)
form* 还是很简单,它只是一些形式,基本上是隐含的progn。对于keys,它告诉我这是一个对象列表的指示符。呸。我的问题从这里开始……
This document 告诉我指示符是:
一个表示另一个对象的对象。
嗯。由于case 正在与eq 合作,我本以为我需要在这里给出一个符号。为什么keys 是list 对象的指示符,而不是单个对象?我可以在一个分支中比较多个符号吗?我想这里的问题归结为没有真正理解designator 的含义,但也许有人可以帮助我并将我推向正确的方向。你会如何解释 Lisp 中的指示符是什么?
然后,我开始使用代码,我注意到如果我删除 ' 字符,事情仍然有效。代码
(defun fizz-buzz (n)
(princ (case (is-fizz-buzz n)
(fizz "Fizz!")
(buzz "Buzz!")
(fizz-buzz "Fizz-Buzz!")
(otherwise n))))
产生与上面的代码完全相同的结果。为什么是这样?我什至根本没想到这是可执行的,因为(fizz "Fizz!") 对我来说看起来像是fizz 的函数调用,它不存在。为什么会这样?
然后,最后一个问题是,当我跑步时
(case 'quote ('foo 1) ('bar 2))
它返回1(这似乎不合逻辑,我原以为nil)。如果我将其更改为
(case 'quote ('foo 1) ('bar 2) (otherwise 3))
它仍然返回1,而不是我现在所期望的3。从文档中我不明白为什么我的 otherwise-clause 显然不应该做什么。
任何提示为什么这两种情况的行为如此?
【问题讨论】:
-
其元素是那个非零原子)或一个适当的列表(表示它自己)。”因此符号
fizz和列表(fizz)都表示列表(fizz),列表@ 987654358@ 指定自己等
标签: lisp common-lisp