A few quick tips: '(0 0 0) technically creates an immutable object and
the consequences of modifying it are undefined. Also, why are you
using setf here anyway? It appears quite unnecessary to modify the
argument when you should simply be returning a newly constructed value.
--
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
eugene kim wrote:
>
> hi all..
>
> i'm trying to make a function which returns list of 3 numbers
> it's recursive and it modifies using "setf" the list when neccessary at
> each recursion step
>
> problem is when even though i define the list locally..as (0 0 0)
Well, it's local but it's a literal. if you know "c" this is like
modifying:
char *howdy = "Howdy!!!";
I did not look at your code since the symptom you describe seems to fit
my guess that by using the literal '(0 0 0) you simply /are/ working on
the same list each time.
Try (list 0 0 0) instead. That ensures a new list.
Once that works, you might reconsider whether recursion adds any value
over dolist, and whether you cannot just track three local values and
then return a list of them as the final step.
(defun guess-num-sexes-friends (user)
( let ((friends (getAttribute user 'friends)))
( guess-num-sexes-friends-internal friends (list 0 0 0))))
(defun guess-num-sexes-friends-internal (friends aList)
(print aList)
(cond ((null friends) (list 0 0 0)) ;; why another list?
((> (guessSex-num (first friends)) 0)
(setf (first aList) (+ 1 (first
(guess-num-sexes-friends-internal
(rest friends) aList))))
aList)
((< (guessSex-num (first friends)) 0)
(setf (second aList) (- (second
(guess-num-sexes-friends-internal
(rest friends) aList)) 1))
aList)
(t (setf (third aList) (+ 1 (third
(guess-num-sexes-friends-internal (rest friends) aList))))
aList)))
; that's not really recursion in any interesting sense, you could just
as well code:
(defun guess-num-sexes-friends (user)
( let ((alist (list 0 0 0))
(friends (getAttribute user 'friends)))
( guess-num-sexes-friends-internal friends alist)))
(defun guess-num-sexes-friends-internal (friends aList)
(when friends
(print aList)
(guess-num-sexes-friends-internal (rest friends) aList) ;; throw
away return value without effect
(cond ((> (guessSex-num (first friends)) 0)
(setf (first aList) (+ 1 (first aList))))
((< (guessSex-num (first friends)) 0)
(setf (second aList) (- (second alist) 1)))
(t (setf (third aList) (+ 1 (third alist)))))
(values))) ;; just to make a point that the return value does not
matter as you have things
; do you know about minusp, plusp, incf, decf?...
(defun guess-num-sexes-friends-internal (friends aList)
(when friends
(print aList)
(guess-num-sexes-friends-internal (rest friends) aList)
(cond ((plusp (guessSex-num (first friends)))
(incf (first aList)))
((minusp (guessSex-num (first friends)))
(decf (second aList)))
(t (incf (third aList)))))
(values))
; one good thing about lisp is not having to make separate helper
functions:
(defun guess-num-sexes-friends (user)
(let ((alist (list 0 0 0)))
(dolist (friend (getAttribute user 'friends) alist)
(print aList)
(cond ((plusp (guessSex-num friend))
(incf (first aList)))
((minusp (guessSex-num friend))
(decf (second aList)))
(t (incf (third aList)))))))
;; finally, this is clearer:
(defun guess-num-sexes-friends (user)
(let ((sex+ 0) (sex- 0) (sex0 0))
(dolist (friend (getAttribute user 'friends) (list sex+ sex- sex0))
(print aList)
(cond ((plusp (guessSex-num friend)) (incf sex+))
((minusp (guessSex-num friend)) (decf sex-))
(t (incf sex0))))))
--
kenny tilton
clinisys, inc
---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
Elwood P. Dowd
mdanish thank you
thank you kenny again..
well,
final is next week, i'm not taking class about lisp
i'm just trying to grasp simple syntax first..
however, i'll look through your kind answer carefully whenever i have
time..
thank you again.
hey, eugene...
sorry, i almost added the caveat "completely untested", but got lazy and
left it out.
corrected:
(defun guess-num-sexes-friends (user)
(let ((sex+ 0) (sex- 0) (sex0 0))
(dolist (friend (getAttribute user 'friends) (list sex+ sex- sex0))
;;; (print aList) <======== left in inadvertently while hacking
away at your version
(cond ((plusp (guessSex-num friend)) (incf sex+))
((minusp (guessSex-num friend)) (decf sex-))
(t (incf sex0))))))
...that (print aList) is just a debugging line left over from your
version. Take it out and all is well.
As for understanding the code, observe that (INCF <place>) is like (SETF
<place> (+ 1 <place>) and that (> <any> 0) can be coded (plusp <any>).
btw, if you really want to start with a list or you really want to use
recursion, here are some other approaches (tested) to look at:
(defun gnsf (user)
(labels ((gnsfi (friends)
(if (null friends)
(list 0 0 0)
(let ((resulti (gnsfi (rest friends)))
(this-guess (guessSex-num (first friends))))
(cond ((plusp this-guess) (incf (first resulti)))
((minusp this-guess) (decf (second resulti)))
(t (incf (third resulti))))
resulti))))
(gnsfi (getAttribute user 'friends))))
(defun gnsf2 (user)
(let ((result (list 0 0 0)))
(mapc (lambda (friend)
(let ((this-guess (guessSex-num friend)))
(cond ((plusp this-guess) (incf (first result)))
((minusp this-guess) (decf (second result)))
(t (incf (third result))))))
(getAttribute user 'friends))
result))
--
kenny tilton
clinisys, inc
---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
Elwood P. Dowd