我猜这应该是LISP很容易做到的事情(他们之所以这么称呼它),但我无法绕过它。
我们说我有以下列表:
((1 2 3)(4(5 6)))
我想将它们全部添加,因此结果应为21
我开始很容易,尝试从一个好的列表中添加元素(如(1 2 3)),我几乎做到了:
(defun sum (list)
(if list
(+ (car list) (sum (cdr list)))
0)
)
可能有更好的编码方式和更好的排列方式,但是现在这种(几乎像C语言)缩进样式可以帮助我跟踪我的括号。它有效。
不幸的是,对于我的示例中的列表来说,它还不够好。所以我再试一次:
(defun sum (list)
(cond
( (atom (car list)) (+ (car list) (sum (cdr list))) )
( (list (car list)) (+ (sum (car list) ) (sum (cdr list))))
)
)
这看起来并不过分,因为即使对于简单的示例我也会出现堆栈溢出错误。
编辑: 我设法写了一个工作(而不是那么复杂)的功能:
(defun sum (l)
(cond
((null l) 0)
((atom (car l)) (+ (car l) (sum (cdr l))))
((+ (sum (car l)) (sum (cdr l))))
)
)
答案 0 :(得分:3)
你说:
可能有更好的编码方式和更好的排列方式,但是现在这种(几乎像C语言)缩进样式可以帮助我跟踪我的括号。它有效。
任何现代编辑都会帮助你。编辑器缩进并计算括号。缩进是正确的,这一点非常重要。
格式化Lisp代码的最佳方法是:
(defun sum (list)
(if list
(+ (car list)
(sum (cdr list)))
0))
编写函数的更好方法是这样的:
(defun sum (list)
(cond ((null list) 0) ; termination test first
((atom (first list)) (+ (first list) ; FIRST not CAR
(sum (rest list)))) ; REST not CDR
(t (+ (sum (first list))
(sum (rest list))))))
略有不同的版本:
(defun sum (list)
(if (null list) ; termination test first
0 ; termination value
(destructuring-bind (head . tail) ; bind variables
list ; matching with LIST
(+ (if (atom head) ; all list elements are numbers
head
(sum head))
(sum tail)))))
答案 1 :(得分:2)
你非常接近。调整你的第一个变种:
(defun sum (list)
(if list
(+ (sum (car list)) (sum (cdr list)))
0)
)
因为(car list)
本身可能是一个列表,不一定是数字。
所以现在我们必须让这个工作,以防 一个数字 - 而且不仅car
,而且cdr
也是:
(defun sum (list)
(if (not (listp list))
; an obvious result here...
...
; or else it's a list
(+ (sum (car list)) (sum (cdr list)))
0)
)
但是等等,这里确实有三个个案例 - 一个非空列表,一个空列表,而不是一个列表。相应地修改代码。