From: Will Hartung
Subject: Strange list problems
Date: 
Message-ID: <3ca20843$1_9@news.1usenet.com>
Hi all,

I seem to be encountering some strange side effect issues with constant
lists, and I'm wondering if I've bumped into the possible cause.

Here's an example:

(defun task-rules (task)
  (let ((taskid (intern (format nil "TASK~A" (new-unique))))
        (varid (intern (format nil "TASKSTR~A" (new-unique)))))
    (add-var `(,varid type string init (set ,varid "")))
    (let ((code '(begin)))
      (dolist (tg (task-groups task))
        (format t "~&~%     Building Code = ~A" code)
        (push (simple-code-for-task-group tg varid) code))
      (format t "~&~%     Pre IF Code = ~A" code)
      (push (print `(if (<> ,varid "") (task ,(task-name task)))) code)
      (format t "~&~%     Code = ~A" code)
      (add-rule taskid (print (nreverse code)))
      (list taskid))))

The issue is that when I run this function the first time, every is just
fine.

When I run it again, however, sometimes I would get extraneous 'code'.

I had found that when I recompiled my entire file, the problem went away,
but when I recompiled individual functions (not necessarily this function),
then the problem persisted.

What I think is happening is that in the second (let ...) I have:
(let ((code '(begin)))

It appears to me that the compiler is making a static version of this list
and set 'code' to it, rather than recreating the list every time task-rules
is executed.

Is this what I'm seeing? Should I essentially run through my code and change
all of the list constants (i.e. '(begin)) to expressions (i.e. (list
'begin))?

Are the backquote constants treated the same?

It's been a fairly insidious and hard to track bug in my code, and this is
the "Aha" that I've stumbled upon, and I'm wondering if I'm right.

This is running the LispWorks Personal Edition.

As you can see there's a lot of debug statements in there as I've tried to
hunt this down.

Thanx!

Best Regards,

Will Hartung
(·····@msoft.com)

From: Coby Beck
Subject: Re: Strange list problems
Date: 
Message-ID: <pcoo8.371470$A44.21405924@news2.calgary.shaw.ca>
"Will Hartung" <·····@msoft.com> wrote in message
·················@news.1usenet.com...
> Hi all,
>
> I seem to be encountering some strange side effect issues with constant
> lists, and I'm wondering if I've bumped into the possible cause.
>
> Here's an example:
>
[snip]
>
> What I think is happening is that in the second (let ...) I have:
> (let ((code '(begin)))
>
> It appears to me that the compiler is making a static version of this list
> and set 'code' to it, rather than recreating the list every time
task-rules
> is executed.
>

I think you have identified the cause correctly.


> Is this what I'm seeing? Should I essentially run through my code and
change
> all of the list constants (i.e. '(begin)) to expressions (i.e. (list
> 'begin))?
>

Yes you should.  The results of modifying a constant is undefined, using '
creates a constant structure.

> Are the backquote constants treated the same?

I believe that implementations are free to treat backquotes in a variety of
ways, including ways that involve quoting structure as you have explicitly
done above.  So you should take the same precaution with backquote as with
quote.

> It's been a fairly insidious and hard to track bug in my code, and this is
> the "Aha" that I've stumbled upon, and I'm wondering if I'm right.
>

You are not alone in being bitten by that judging by the frequency of the
problem!

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Tim Moore
Subject: Re: Strange list problems
Date: 
Message-ID: <a7t69i$2mt$0@216.39.145.192>
On Wed, 27 Mar 2002 10:20:44 -0800, Will Hartung <·····@msoft.com> wrote:
>Hi all,
>
>I seem to be encountering some strange side effect issues with constant
>lists, and I'm wondering if I've bumped into the possible cause.
>
>Here's an example:
>
>(defun task-rules (task)
>  (let ((taskid (intern (format nil "TASK~A" (new-unique))))
>        (varid (intern (format nil "TASKSTR~A" (new-unique)))))
>    (add-var `(,varid type string init (set ,varid "")))
>    (let ((code '(begin)))
>      (dolist (tg (task-groups task))
>        (format t "~&~%     Building Code = ~A" code)
>        (push (simple-code-for-task-group tg varid) code))
>      (format t "~&~%     Pre IF Code = ~A" code)
>      (push (print `(if (<> ,varid "") (task ,(task-name task)))) code)
>      (format t "~&~%     Code = ~A" code)
>      (add-rule taskid (print (nreverse code)))
>      (list taskid))))
>
>The issue is that when I run this function the first time, every is just
>fine.
>
>When I run it again, however, sometimes I would get extraneous 'code'.
>
>I had found that when I recompiled my entire file, the problem went away,
>but when I recompiled individual functions (not necessarily this function),
>then the problem persisted.
>
>What I think is happening is that in the second (let ...) I have:
>(let ((code '(begin)))
>
>It appears to me that the compiler is making a static version of this list
>and set 'code' to it, rather than recreating the list every time task-rules
>is executed.

Yes.

>
>Is this what I'm seeing? Should I essentially run through my code and change
>all of the list constants (i.e. '(begin)) to expressions (i.e. (list
>'begin))?

No.  If you change nreverse to reverse things should work, provided that 
other code of yours isn't destructively modifiying the result of task-rules.

>
>Are the backquote constants treated the same?
>

Possibly; it can depend on the cleverness of your implementation.  Constant 
list tails in backquote will probably be constants.

Tim