Path: ...!npeer.as286.net!npeer-ng0.as286.net!3.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: "B. Pym" Newsgroups: comp.lang.lisp Subject: Re: Simple recursive list processing question Date: Tue, 25 Jun 2024 07:33:41 -0000 (UTC) Organization: A noiseless patient Spider Lines: 81 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Injection-Date: Tue, 25 Jun 2024 09:33:41 +0200 (CEST) Injection-Info: dont-email.me; posting-host="f3516bad7bad6e8b4774a100ca8eaa7a"; logging-data="1543152"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19ooQjEBW+eZF6kc8NrF8Ma" User-Agent: XanaNews/1.18.1.6 Cancel-Lock: sha1:lkZEb93rPlTjzvB9bdKBViLIZ1s= Bytes: 3311 > > (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. Scheme: (define (summit lst) (do ((lst lst (cdr lst)) (sum 0 (+ sum (or (car lst) 0)))) ((null? lst) sum))) (summit '(1 #f #f 3 #f 5 7 9)) ===> 25