谁能向我解释为什么这个 lisp 代码不起作用?
can anyone explain to me why this lisp code doesn't work?
它应该计算列表的元素,但显示“*** - +:NIL 不是数字”
(setq A '(2 3 4 3 2 6 7 8 4 3 5 6))
(defun big (A)
(if (not (null (car A))) (+ 1 (big (cdr A))) ) ;if the first element is not null, add 1 to the count of the elements to the rest of the list
)
(print (big A))
null car 的测试没有任何用处,cdr 将在 car 之前 return nil。
你需要一个基本案例,你会发现你已经完成了 return 一些东西而不是递归。现在你没有那个。查看简单递归函数的示例,了解它们如何具有基本情况。
要计算列表中的元素有两种情况:
列表为空的基本情况 (return 0)
列表不为空的递归情况(return1+传入列表的cdr数)
输入错误
一个 IF
表达式有 2 个或 3 个参数:
(if test something)
(if test something something-else)
当它只有 2 个参数时,就好像第三个参数 something-else
是 NIL。这意味着当 test
表达式为假时,IF
表达式的计算结果为 NIL。在你的例子中,你有 2 个参数:
(defun big (A)
(if (not (null (car A)))
;; "then" branch (when condition is true)
(+ 1 (big (cdr A)))
;; no "else" branch (when condition is false)
))
所以你知道有时调用 big
可能 return NIL
.
但是,你还写:
(+ 1 (big (cdr A)))
这个表达式看起来像 (+ 1 x)
,其中 x
是对 big
的调用,这意味着 x
在某些情况下可能计算为 NIL。这就是你用调试器遇到的情况。
如果你确保 if
表达式总是 return 一个数字,例如在 else 分支中 returning 零,那么你不会有相同的错误尝试向 NIL
.
添加一个数字
计算元素
但是,你仍然会有其他错误,因为你说函数 big
“应该计算列表的元素”。如果你想统计一个列表的元素,你永远不需要查看列表中存储的元素,你只需要知道它们存在。
当您写 (car a)
时,您正在访问列表的第一个元素。然后您检查该值是否为非零,但是让一个列表充满 NIL 值是完全有效的:
'(NIL NIL NIL)
该列表有 3 个元素,在计算它们时,它们为 NIL 的事实在任何时候都不重要。
处理列表的递归函数通常需要涵盖两种情况,即列表是否为空。您可以通过调用 (null list)
或 (endp list)
检查当前列表是否为空(只需执行 (if list ... ...)
也可以,因为 NIL 是唯一的假值)。
它应该计算列表的元素,但显示“*** - +:NIL 不是数字”
(setq A '(2 3 4 3 2 6 7 8 4 3 5 6))
(defun big (A)
(if (not (null (car A))) (+ 1 (big (cdr A))) ) ;if the first element is not null, add 1 to the count of the elements to the rest of the list
)
(print (big A))
null car 的测试没有任何用处,cdr 将在 car 之前 return nil。
你需要一个基本案例,你会发现你已经完成了 return 一些东西而不是递归。现在你没有那个。查看简单递归函数的示例,了解它们如何具有基本情况。
要计算列表中的元素有两种情况:
列表为空的基本情况 (return 0)
列表不为空的递归情况(return1+传入列表的cdr数)
输入错误
一个 IF
表达式有 2 个或 3 个参数:
(if test something)
(if test something something-else)
当它只有 2 个参数时,就好像第三个参数 something-else
是 NIL。这意味着当 test
表达式为假时,IF
表达式的计算结果为 NIL。在你的例子中,你有 2 个参数:
(defun big (A)
(if (not (null (car A)))
;; "then" branch (when condition is true)
(+ 1 (big (cdr A)))
;; no "else" branch (when condition is false)
))
所以你知道有时调用 big
可能 return NIL
.
但是,你还写:
(+ 1 (big (cdr A)))
这个表达式看起来像 (+ 1 x)
,其中 x
是对 big
的调用,这意味着 x
在某些情况下可能计算为 NIL。这就是你用调试器遇到的情况。
如果你确保 if
表达式总是 return 一个数字,例如在 else 分支中 returning 零,那么你不会有相同的错误尝试向 NIL
.
计算元素
但是,你仍然会有其他错误,因为你说函数 big
“应该计算列表的元素”。如果你想统计一个列表的元素,你永远不需要查看列表中存储的元素,你只需要知道它们存在。
当您写 (car a)
时,您正在访问列表的第一个元素。然后您检查该值是否为非零,但是让一个列表充满 NIL 值是完全有效的:
'(NIL NIL NIL)
该列表有 3 个元素,在计算它们时,它们为 NIL 的事实在任何时候都不重要。
处理列表的递归函数通常需要涵盖两种情况,即列表是否为空。您可以通过调用 (null list)
或 (endp list)
检查当前列表是否为空(只需执行 (if list ... ...)
也可以,因为 NIL 是唯一的假值)。