'A'不是预期类型'REAL'

时间:2012-07-10 13:22:12

标签: lisp

服务器下面的代码,用于显示列表中的整数。

(defun isNum (N)
  (and (<= N 9) (>= N 0)))

(defun count-numbers (list)
  (let ((count 0))
    (dolist (item list count)
      (cond
       ((null list) nil)
       (((and (<= N 9) (>= N 0))) item)(incf count))
       (setq(0 + count))))))

运行命令时出现错误A' is not of the expected type REAL' (count-numbers'(3 4 5 6 a 7 b))

2 个答案:

答案 0 :(得分:6)

我很惊讶它完全运行,因为你的cond构造不正确,你在代码的不必要的副作用生成位中切换到中缀符号,并且你在{中使用未绑定的变量{1}}。假设,如果它确实运行,那么这个错误听起来是正确的。您正在对参数进行数值比较(以及非数字输入上的错误)。

今天我已经有了我的代码审查帽,所以让我们更深入地了解一下。


Lisp(它实际上无关紧要,这适用于CL,Scheme和所有的mongrels)使用count-numbers,而不是lower-case-snake-case-with-dashes用于变量和函数名称。

lowerCamelCase

Common Lisp约定是使用(defun is-num (n) (and (<= n 9) (>= n 0))) p结束谓词,而不是以-p开头。 Scheme具有(IMO更好)约定结束谓词is-而不是

?

(defun num-p (n) (and (<= n 9) (>= n 0))) 不是你如何调用函数。你实际上需要使用它的名字,而不仅仅是试图调用它的身体。如果您尝试运行此代码,则会出现许多错误之一。

((and (<= N 9) (>= N 0)))

(defun count-numbers (list) (let ((count 0)) (dolist (item list count) (cond ((null list) nil) ((num-p item) item)(incf count)) (setq(0 + count)))))) 已经存在,并对其输入进行类型检查,而不是尝试进行数值比较。您可能应该使用它。

numberp

(defun count-numbers (list) (let ((count 0)) (dolist (item list count) (cond ((null list) nil) ((numberp item) item)(incf count)) (setq(0 + count)))))) 可能不会按照((numberp item) item) (incf count))条款执行您认为的操作。它实际上被视为两个单独的条款;一个检查cond是否为item,如果是,则返回number。第二个尝试检查变量incf并返回count,如果它的计算结果为t(它不会,也不会)。您似乎想要的是在列表中找到一个数字时递增计数器count,这意味着您应该将incf子句放入item

(defun count-numbers (list)
  (let ((count 0))
    (dolist (item list count)
      (cond ((null list) nil)
            ((numberp item) 
             (incf count)
             item))
      (setq (0 + count)))))

出于三个原因,

(setq (0 + count))是错误的

  • 您似乎已经重新使用中缀表示法,这意味着第二位实际上尝试使用变量0+作为参数调用函数count。 / LI>
  • 您没有setq的第二部分,这意味着您正试图隐含地将上述内容设置为NIL
  • 您实际上不需要设置任何内容以返回值

此时,我们终于有一段代码可以评估并正常运行(并且它不会引发您在上面提到的错误)。

(defun count-numbers (list)
  (let ((count 0))
    (dolist (item list count)
      (cond ((null list) nil)
            ((numberp item) 
             (incf count)
             item))
      count)))

dolist是一个迭代构造,它为给定列表中的每个元素执行某些操作。这意味着您实际上不需要使用cond手动测试列表终止。此外,由于dolist未收集结果,因此没有理由将item返回给它。您还会不必要地隐藏您在count中声明的本地let

(defun count-numbers (list)
  (let ((count 0))
    (dolist (item list)
      (when (numberp item) (incf count)))
    count))

像往常一样,您可以通过更简单的loop来完成所有这些操作。

(defun count-numbers (list)
  (loop for item in list
        when (numberp item) sum 1))

使计数器隐含,并使您无需手动返回。实际上,除非这是一个编写自己的迭代函数的练习,否则Common Lisp有一个内置的count-if,它需要predicate sequence [some other options]并返回countsequence个项目匹配predicate。如果您想特别命名count-numbers,出于风格原因,您可以

(defun count-numbers (list) (count-if #'numberp list))

并完成它。


总之,好好尝试,但请在reading up家庭language上尝试for realzies,然后再提出问题。

答案 1 :(得分:0)

另一种方法是:

(reduce
 #'(lambda (a b)
     (if (numberp b) (1+ a) a))
 '(3 4 5 6 a 7 b) :initial-value 0) ; 5

即。以每次迭代给出的方式处理序列,前一次迭代的结果+序列的下一个成员。从零开始并在每次序列中的元素为数字时递增结果。

修改

对不起,我还没有看到Inaimathi提到count-if。那可能会更好。