From: Zachary Turner
Subject: Lisp Memory allocation question
Date: 
Message-ID: <776920BE56306FA0.6200279D5DC16A7A.CA7DD5288ECCF770@lp.airnews.net>
Hi, i have a function that executes some code similar to the following
(stripped down for simplicity):

defun somefunc()
    (some_other_func '(nil nil nil nil nil nil nil nil nil)))

(defun some_other_func (lst)
    (replace lst 'blah :start1 0))

some_other_func basically replaces the first element of the list passed in
with 'blah, resulting in
'(blah nil nil nil nil nil nil nil nil)

This is fine, but the next time I execute somefunc() from the toplevel, it
passes '(blah nil nil nil nil nil nil nil nil).  Why does this happen?  I
hardcoded the definition of the list, shouldn't it use this definition every
single time?  Obviously the solution is to use (replace (copy-list lst)
'blah :start1 0), but I'm just trying to understand the language better.

 - Zach

From: Rainer Joswig
Subject: Re: Lisp Memory allocation question
Date: 
Message-ID: <rainer.joswig-898051.23203325022000@news.is-europe.net>
In article 
<··················································@lp.airnews.net>, 
"Zachary Turner" <·······@bindview.com> wrote:

> Hi, i have a function that executes some code similar to the following
> (stripped down for simplicity):
> 
> defun somefunc()
>     (some_other_func '(nil nil nil nil nil nil nil nil nil)))
> 
> (defun some_other_func (lst)
>     (replace lst 'blah :start1 0))
> 
> some_other_func basically replaces the first element of the list passed in
> with 'blah, resulting in
> '(blah nil nil nil nil nil nil nil nil)
> 
> This is fine, but the next time I execute somefunc() from the toplevel, it
> passes '(blah nil nil nil nil nil nil nil nil).  Why does this happen?

The list is a constant. It is even not generally correct to modify it.

Use (list nil nil nil nil nil nil nil nil nil) to get a fresh list.

Rainer Joswig, ISION Internet AG, Harburger Schlossstra�e 1, 
21079 Hamburg, Germany, Tel: +49 40 77175 226
Email: ·············@ision.de , WWW: http://www.ision.de/
From: Rahul Jain
Subject: Re: Lisp Memory allocation question
Date: 
Message-ID: <899tg9$9qh$1@joe.rice.edu>
In article <··················································@lp.airnews.net>
posted on Friday, February 25, 2000  2:22 PM, "Zachary Turner"
<·······@bindview.com> wrote:
> Hi, i have a function that executes some code similar to the following
> (stripped down for simplicity):
> 
> defun somefunc()
>     (some_other_func '(nil nil nil nil nil nil nil nil nil)))

What this code does is pass the quoted list as a /constant/. Whenever you
do something like '(...), the list is assumed to be a constant and is not copied
before passing it as a parameter. You want to use (list nil nil nil nil....)
instead if you're going to be mutating this list.

> 
> (defun some_other_func (lst)
>     (replace lst 'blah :start1 0))
> 
> some_other_func basically replaces the first element of the list passed in
> with 'blah, resulting in
> '(blah nil nil nil nil nil nil nil nil)
> 
> This is fine, but the next time I execute somefunc() from the toplevel, it
> passes '(blah nil nil nil nil nil nil nil nil).  Why does this happen?  I
> hardcoded the definition of the list, shouldn't it use this definition every
> single time?  Obviously the solution is to use (replace (copy-list lst)
> 'blah :start1 0), but I'm just trying to understand the language better.

Of course, that is the other solution to the problem (but note that copy-list
only copies the topmost level of the list, use copy-tree for a deep copy, and
see a recent thread for more info on this)

-- 
-> -\-=-=-=-=-=-=-=-=-=-/^\-=-=-=<*><*>=-=-=-/^\-=-=-=-=-=-=-=-=-=-/- <-
-> -/-=-=-=-=-=-=-=-=-=/ {  Rahul -<>- Jain   } \=-=-=-=-=-=-=-=-=-\- <-
-> -\- "I never could get the hang of Thursdays." - HHGTTG by DNA -/- <-
-> -/- http://photino.sid.rice.edu/ -=- ·················@usa.net -\- <-
|--|--------|--------------|----|-------------|------|---------|-----|-|
   Version 11.423.999.210020101.23.50110101.042
   (c)1996-2000, All rights reserved. Disclaimer available upon request.
From: Espen Vestre
Subject: Re: Lisp Memory allocation question
Date: 
Message-ID: <w6zoslvgm1.fsf@wallace.nextel.no>
Rahul Jain <·····@rice.edu> writes:

> What this code does is pass the quoted list as a /constant/. Whenever you
> do something like '(...), the list is assumed to be a constant and is not copied
> before passing it as a parameter. You want to use (list nil nil nil nil....)
> instead if you're going to be mutating this list.

What is even more difficult to remember, is that you can't use backquote
notation either for lists that may be destructively modified.
-- 
  (espen)
From: Tim Bradshaw
Subject: Re: Lisp Memory allocation question
Date: 
Message-ID: <ey366v9r328.fsf@cley.com>
* Espen Vestre wrote:

> What is even more difficult to remember, is that you can't use
> backquote notation either for lists that may be destructively
> modified.

Does the spec say this?  I'd say it's silly if it does because it
would be implementationally extraordinarily hard to achieve in
general.  Consider something like:

    (defun foo (x)
      `(1 2 3 ,x))

Of course a backquoted list which does not have any unquoting in is a
different matter.

--tim
From: Espen Vestre
Subject: Re: Lisp Memory allocation question
Date: 
Message-ID: <w6g0udv7ff.fsf@wallace.nextel.no>
Tim Bradshaw <···@cley.com> writes:

> * Espen Vestre wrote:
> 
> > What is even more difficult to remember, is that you can't use
> > backquote notation either for lists that may be destructively
> > modified.
> 
> Does the spec say this?  I'd say it's silly if it does because it
> would be implementationally extraordinarily hard to achieve in
> general.  Consider something like:

See:

http://www.harlequin.com/support/books/HyperSpec/Body/sec_2-4-6.html

and note:

"The constructed copy of the template might or might not share list
 structure with the template itself."

Example:

K2(117): (defun foo (x)
	   `(a ,x b c))
FOO
K2(118): (compile *)
FOO
NIL
NIL
K2(120): (setf test (foo 1))
(A 1 B C)
K2(126): (nthcdr 3 test)
(C)
K2(129): (setf (first *) 'd)
D
K2(131): (foo 2)
(A 2 B D)

...and to add to the confusion: ACL 5.0.1 (which I use), optimizes
with structure-sharing only when you compile (the above example gives
you (A 2 B C) if you omit the compile), so if you tend to work with
interpreted code when debugging and aren't aware of this problem, you
can get *really* confused!
-- 
  (espen)
From: Tim Bradshaw
Subject: Re: Lisp Memory allocation question
Date: 
Message-ID: <ey3u2itpghv.fsf@cley.com>
* Espen Vestre wrote:

> "The constructed copy of the template might or might not share list
>  structure with the template itself."

I think this came up recently, and the eventual conclusion was that
it's safe to assume that backquote will only create read-only
structure where it `can'.  (So in `(a b ,c d e), the tail beginning d
could be shared and read-only but the (a b ...) won't be.) An
implementation which did other than that would have to be pretty
gratuitously nasty -- it would have to intentionally copy the whole
list into read-only space.  I agree that the standard would allow
that.

--tim
From: Pierre R. Mai
Subject: Re: Lisp Memory allocation question
Date: 
Message-ID: <87puths92w.fsf@orion.dent.isdn.cs.tu-berlin.de>
Tim Bradshaw <···@cley.com> writes:

> * Espen Vestre wrote:
> 
> > What is even more difficult to remember, is that you can't use
> > backquote notation either for lists that may be destructively
> > modified.
> 
> Does the spec say this?  I'd say it's silly if it does because it
> would be implementationally extraordinarily hard to achieve in
> general.  Consider something like:
> 
>     (defun foo (x)
>       `(1 2 3 ,x))

See the entry 2.4.6 Backquote: After giving the outline of an
implementation that would always freshly cons, they say the following:

"
An implementation is free to interpret a backquoted form F1 as any form F2
that, when evaluated, will produce a result that is the same under equal as
the result implied by the above definition, provided that the side-effect
behavior of the substitute form F2 is also consistent with the description
given above. The constructed copy of the template might or might not share
list structure with the template itself. As an example, the above definition
implies that


 `((,a b) ,c ,@d)

will be interpreted as if it were


 (append (list (append (list a) (list 'b) 'nil)) (list c) d 'nil)

but it could also be legitimately interpreted to mean any of the following:


 (append (list (append (list a) (list 'b))) (list c) d)
 (append (list (append (list a) '(b))) (list c) d)
 (list* (cons a '(b)) c d)
 (list* (cons a (list 'b)) c d)
 (append (list (cons a '(b))) (list c) d)
 (list* (cons a '(b)) c (copy-list d))
"

So it seems to me that one cannot rely on unshared structure or
modifiable structure (the '(b) above could come to lie in read-only
space, thereby making certain modifications impossible to do).

Regs, Pierre.

-- 
Pierre Mai <····@acm.org>         PGP and GPG keys at your nearest Keyserver
  "One smaller motivation which, in part, stems from altruism is Microsoft-
   bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]