(defun summit (a-list)
(if (not (null a-list))
(let ((x (car a-list)))
(if (null x)
(summit (cdr a-list))
(+ x (summit (cdr a-list)))))))
Now it doesn't enter infinite loop, however it doesn't work even
for the lists that doesn't contain any nil elements:
CL-USER> (summit (list 1 2))
And the SBCL debugger complains:
Argument Y is not a NUMBER: NIL
[Condition of type SIMPLE-TYPE-ERROR]
It seems like I'm trying to do addition using some number
and something that is not a number (a nil?).
I just couldn't find how to correct it? Can somebody enlighten me?
Your second post shows that you've solved the problem, so maybe you've already figured this out. But notice in your solution above that the
outer IF does not supply an explicit "else" value. The default is for IF
to return NIL when the test fails and no "else" clause is provided. This
is what happens when your first version reaches the end of the list:
(summit (list 1 2))
1. Trace: (SUMMIT '(1 2))
2. Trace: (SUMMIT '(2))
3. Trace: (SUMMIT 'NIL)
3. Trace: SUMMIT ==> NIL
*** - argument to + should be a number: NIL
The 2nd call to SUMMIT is waiting to add 2 to the result of the 3rd
call, which returns NIL by default.
In case you're interested, here are a few ways to solve Graham's problem:
;;;
;;; Ex. 9
;;;
(defun summit-1 (l)
(apply #'+ (remove nil l)))
(defun summit-2 (l)
(reduce #'+ (remove nil l)))
(defun summit-3 (l)
(if (endp l)
0
(let ((x (first l)))
(if (null x)
(summit-3 (rest l))
(+ x (summit-3 (rest l)))) )))
(defun summit-4 (l)
(cond ((endp l) 0)
((null (first l)) (summit-4 (rest l)))
(t (+ (first l) (summit-4 (rest l)))) ))
(defun summit-5 (l)
(loop for elt in l
when elt
sum elt))
SUMMIT-3 is essentially the same as your second version. The last two
are not really fair since Graham doesn't introduce COND in chapter 2,
and he is allergic to LOOP.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 403 |
Nodes: | 16 (2 / 14) |
Uptime: | 44:08:38 |
Calls: | 8,407 |
Calls today: | 2 |
Files: | 13,171 |
Messages: | 5,905,028 |