From: yaru22
Subject: Why is my local variable value accumulated?
Date: 
Message-ID: <1179500164.891961.49400@q75g2000hsh.googlegroups.com>
Hi,

I was doing an exercise in the book "Common Lisp" by David S.
Touretzky.

It's chapter 11 exercise 11.22 d

(defun count-bases (dna)
  (let ((dnaCnt '((A 0) (T 0) (G 0) (C 0))))
    (labels ((count-element (x)
	       (incf (second (assoc x dnaCnt))))
	     (count-recurse (x)
	       (cond ((null x) t)
		     ((atom (first x)) (and (count-element (first x))
					    (count-recurse (rest x))))
		     (t (and (count-recurse (first x))
			     (count-recurse (rest x)))))))
      (count-recurse dna)
      dnaCnt)))

The code is compiled without a problem.

When I run the program first time by evaluating

(count-bases '((g c) (a t) (t a) (t a) (c g)))

It gives the correct output:
((A 3) (T 3) (G 2) (C 2))

However, if I run it second time,

the answer is accumulated to the one in the above.

So it returns

((A 6) (T 6) (G 4) (C 4))

Why is it happening?

I used local variable dnaCnt to keep track of the occurrences.

But why is it behaving like I'm using global variables?

Thank you.

- Brian

From: Tim Bradshaw
Subject: Re: Why is my local variable value accumulated?
Date: 
Message-ID: <1179504124.822235.202960@q75g2000hsh.googlegroups.com>
On May 18, 3:56 pm, yaru22 <······@gmail.com> wrote:
>
>
> But why is it behaving like I'm using global variables?

Don't modify constants!

A better thing to do with the alist (in general, in this case probably
not as you know only 4 bases will appear I guess, until you get to
deal with alien DNA anyway) would be:

(let ((match (assoc x dnacnt)))
  (if match (inc (cdr match)) (push (cons x 1) dnacnt)))

--tim
From: Zach Beane
Subject: Re: Why is my local variable value accumulated?
Date: 
Message-ID: <m3odki5g4h.fsf@unnamed.xach.com>
yaru22 <······@gmail.com> writes:

> Hi,
> 
> I was doing an exercise in the book "Common Lisp" by David S.
> Touretzky.
> 
> It's chapter 11 exercise 11.22 d
> 
> (defun count-bases (dna)
>   (let ((dnaCnt '((A 0) (T 0) (G 0) (C 0))))
>     (labels ((count-element (x)
> 	       (incf (second (assoc x dnaCnt))))
> 	     (count-recurse (x)
> 	       (cond ((null x) t)
> 		     ((atom (first x)) (and (count-element (first x))
> 					    (count-recurse (rest x))))
> 		     (t (and (count-recurse (first x))
> 			     (count-recurse (rest x)))))))
>       (count-recurse dna)
>       dnaCnt)))
> 
> When I run the program first time by evaluating
> 
> (count-bases '((g c) (a t) (t a) (t a) (c g)))
> 
> It gives the correct output:
> ((A 3) (T 3) (G 2) (C 2))
> 
> However, if I run it second time,
> 
> the answer is accumulated to the one in the above.
> 
> So it returns
> 
> ((A 6) (T 6) (G 4) (C 4))
> 
> Why is it happening?
> 
> I used local variable dnaCnt to keep track of the occurrences.
> 
> But why is it behaving like I'm using global variables?

You should not modify the contents of quoted lists, because this sort
of side effect is allowed to occur. You could get modifiable copies
with:

   (copy-list '((g c) (a t) (t a) (c g)))

Or you could construct the lists fully with the LIST function:

   (list (list 'a 0) (list 't 0) (list 'g 0) (list 'c 0))

Zach
From: Dan Bensen
Subject: Re: Why is my local variable value accumulated?
Date: 
Message-ID: <f2knc5$fh4$1@wildfire.prairienet.org>
yaru22 wrote:
>   (let ((dnaCnt '((A 0) (T 0) (G 0) (C 0))))
> if I run it second time,
> the answer is accumulated to the one in the above.
> Why is it happening?
> why is it behaving like I'm using global variables?

Because it's not allocating a new list.  It's using
the original copy, which still has the old values in it.
As Zach mentioned, you can make a fresh copy of the list
with
   (let ((dnaCnt (copy-list '((A 0) (T 0) (G 0) (C 0)))))

-- 
Dan
www.prairienet.org/~dsb/
From: Ariel Badichi
Subject: Re: Why is my local variable value accumulated?
Date: 
Message-ID: <87646qymx8.fsf@sneeze.site>
Dan Bensen <··········@cyberspace.net> writes:

> yaru22 wrote:
> >   (let ((dnaCnt '((A 0) (T 0) (G 0) (C 0))))
> > if I run it second time,
> > the answer is accumulated to the one in the above.
> > Why is it happening?
> > why is it behaving like I'm using global variables?
> 
> Because it's not allocating a new list.  It's using
> the original copy, which still has the old values in it.
> As Zach mentioned, you can make a fresh copy of the list
> with
>    (let ((dnaCnt (copy-list '((A 0) (T 0) (G 0) (C 0)))))
> 

This would still be wrong; use COPY-TREE.

> -- 
> Dan
> www.prairienet.org/~dsb/
From: Dan Bensen
Subject: Re: Why is my local variable value accumulated?
Date: 
Message-ID: <f2l7lb$l2e$1@wildfire.prairienet.org>
> Dan Bensen <··········@cyberspace.net> writes:
>> you can make a fresh copy of the list with
>>    (let ((dnaCnt (copy-list '((A 0) (T 0) (G 0) (C 0)))))
Ariel Badichi wrote:
> This would still be wrong; use COPY-TREE.
Oops, you're right.  Thanks for catching that.

-- 
Dan
www.prairienet.org/~dsb/