From: ······@gmail.com
Subject: Destructive Functions
Date: 
Message-ID: <1135322567.764842.307640@f14g2000cwb.googlegroups.com>
I had a question I was hoping someone could help me with.  I'm writing
a program where I need to parse this list, but it makes things a lot
easier if I pass it the list in reverse order and some NILs appended to
either side.  Since the lists I'm dealing with are quite long, I wanted
to try to make the code as efficient as possible.  What I tried to do
was this:

(defun fixlist (alst)
  (nreverse (nconc '(NIL)
		   '(NIL)
		   '(NIL)
		   '(NIL)
		   (copy-list alst)
		   '(NIL)
		   '(NIL)
		   '(NIL))))

This code works neither in clisp nor in openmcl.  Or rather, it works
the first time after I load it and then hangs when I try to call it
again.  Changing it to

(defun fixlist (alst)
  (nreverse (append '(NIL)
		   '(NIL)
		   '(NIL)
		   '(NIL)
		   (copy-list alst)
		   '(NIL)
		   '(NIL)
		   '(NIL))))

seems to make it work perfectly in clisp, but in openmcl I get results
like this:

? (fixlist '(1 2 3))
(NIL NIL NIL 3 2 1 NIL NIL NIL NIL)
? (fixlist '(a b c))
(NIL NIL NIL NIL 1 2 3 NIL NIL NIL NIL NIL C B A NIL NIL NIL NIL)

Changing it to

(defun fixlist (alst)
  (reverse (append '(NIL)
		   '(NIL)
		   '(NIL)
		   '(NIL)
		   (copy-list alst)
		   '(NIL)
		   '(NIL)
		   '(NIL))))

and not using any destructive functions at all makes it work in openmcl
as well.

I was wondering if anyone could please exlpain to what problems the
destructive functions are causing.  As far as I can tell I'm only
modifying cons structures I've just created so I thought it would be
okay to use the destructive functions to save time.  Thanks!

From: Pascal Costanza
Subject: Re: Destructive Functions
Date: 
Message-ID: <411nomF1cn0haU1@individual.net>
······@gmail.com wrote:
> I had a question I was hoping someone could help me with.  I'm writing
> a program where I need to parse this list, but it makes things a lot
> easier if I pass it the list in reverse order and some NILs appended to
> either side.  Since the lists I'm dealing with are quite long, I wanted
> to try to make the code as efficient as possible.  What I tried to do
> was this:
> 
> (defun fixlist (alst)
>   (nreverse (nconc '(NIL)
> 		   '(NIL)
> 		   '(NIL)
> 		   '(NIL)
> 		   (copy-list alst)
> 		   '(NIL)
> 		   '(NIL)
> 		   '(NIL))))
[...]

> I was wondering if anyone could please exlpain to what problems the
> destructive functions are causing.  As far as I can tell I'm only
> modifying cons structures I've just created [...]

No, you're not. Quoted lists like '(1 2 3) or (quote (nil)) are literal 
data, just like literal strings ("Hello, World!") or numbers (42), etc. 
A compiler is allowed to create them at compile time and insert them as 
constants in the code. Especially, a compiler is also allowed to have 
multiple literals share the same data, so it can be that in some 
implementations all your '(nil) are one and the same.

You should say (nconc (list nil) (list nil) ...), or (nconc (list nil 
nil nil) ...) instead. (list ...) is guaranteed to create a fresh list 
at runtime.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: ······@gmail.com
Subject: Re: Destructive Functions
Date: 
Message-ID: <1135324110.335206.143460@g43g2000cwa.googlegroups.com>
Thank you very much.  That explains everything.
From: Pascal Bourguignon
Subject: Re: Destructive Functions
Date: 
Message-ID: <871x04fcpb.fsf@thalassa.informatimago.com>
·······@gmail.com" <······@gmail.com> writes:

> Thank you very much.  That explains everything.

I'd write it more concisely as:

(defun fix-list (list)
    (nreverse (append (make-list 4 nil) list (make-list 4 nil))))

Since list is not the last argument of append, it gets copied automatically,

as well as the first list of NIL, but for 4 conses, I prefer the above to:

    (nreverse (nconc (make-list 4 nil) (append list (make-list 4 nil))))  


Another alternative would be:

    (nconc (make-list 4 nil) (reverse (nconc (make-list 4 nil) list)))
or:
    (list* nil nil nil nil (reverse (list* nil nil nil nil list)))

letting REVERSE do the copying of LIST.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"Our users will know fear and cower before our software! Ship it!
Ship it and let them flee like the dogs they are!"
From: http://public.xdi.org/=pf
Subject: Re: Destructive Functions
Date: 
Message-ID: <m2psnoqfhc.fsf@mycroft.actrix.gen.nz>
On Fri, 23 Dec 2005 08:36:53 +0100, Pascal Costanza wrote:

> No, you're not. Quoted lists like '(1 2 3) or (quote (nil)) are
> literal data, just like literal strings ("Hello, World!") or numbers
> (42), etc. A compiler is allowed to create them at compile time and

"Allowed to" is too weak: it's /required/ to (and it doesn't create
them at compile time, it creates them at read time -- QUOTE returns
the very value inside the QUOTE form!)

> insert them as constants in the code. Especially, a compiler is also
> allowed to have multiple literals share the same data, so it can be

The file-compiler can do that; the in-core compiler (COMPILE function)
can't.


-- 
Quid enim est stultius quam incerta pro certis habere, falsa pro veris?
                                                                -- Cicero
(setq reply-to
  (concatenate 'string "Paul Foley " "<mycroft" '(··@) "actrix.gen.nz>"))
From: jayessay
Subject: Re: Destructive Functions
Date: 
Message-ID: <m3bqz7g09s.fsf@rigel.goldenthreadtech.com>
Paul Foley <···@below.invalid> (http://public.xdi.org/=pf) writes:

> On Fri, 23 Dec 2005 08:36:53 +0100, Pascal Costanza wrote:
> 
> > No, you're not. Quoted lists like '(1 2 3) or (quote (nil)) are
> > literal data, just like literal strings ("Hello, World!") or numbers
> > (42), etc. A compiler is allowed to create them at compile time and
> 
> "Allowed to" is too weak: it's /required/ to (and it doesn't create
> them at compile time, it creates them at read time -- QUOTE returns
> the very value inside the QUOTE form!)
> 
> > insert them as constants in the code. Especially, a compiler is also
> > allowed to have multiple literals share the same data, so it can be
> 
> The file-compiler can do that; the in-core compiler (COMPILE function)
> can't.

I believe you are thinking of coalescing here.  Literals (objects) in
COMPILEd code are required to reference (as in eql) the literals
(objects) in the source code.  So, if a literal in the source is
already "coalesced", say by the reader, then the COMPILEd code will
refer to only one such object for that literal.  So, the thrust of
what Pascal is saying here still stands.


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Barry Margolin
Subject: Re: Destructive Functions
Date: 
Message-ID: <barmar-BC8171.13342023122005@comcast.dca.giganews.com>
In article <··············@rigel.goldenthreadtech.com>,
 jayessay <······@foo.com> wrote:

> Paul Foley <···@below.invalid> (http://public.xdi.org/=pf) writes:
> 
> > On Fri, 23 Dec 2005 08:36:53 +0100, Pascal Costanza wrote:
> > 
> > > No, you're not. Quoted lists like '(1 2 3) or (quote (nil)) are
> > > literal data, just like literal strings ("Hello, World!") or numbers
> > > (42), etc. A compiler is allowed to create them at compile time and
> > 
> > "Allowed to" is too weak: it's /required/ to (and it doesn't create
> > them at compile time, it creates them at read time -- QUOTE returns
> > the very value inside the QUOTE form!)
> > 
> > > insert them as constants in the code. Especially, a compiler is also
> > > allowed to have multiple literals share the same data, so it can be
> > 
> > The file-compiler can do that; the in-core compiler (COMPILE function)
> > can't.
> 
> I believe you are thinking of coalescing here.  Literals (objects) in
> COMPILEd code are required to reference (as in eql) the literals
> (objects) in the source code.  So, if a literal in the source is
> already "coalesced", say by the reader, then the COMPILEd code will
> refer to only one such object for that literal.  So, the thrust of
> what Pascal is saying here still stands.

The reader is not allowed to coalesce constants, AFAIK.  Only the 
file-compiler can.  I think the justification for this is that it's 
difficult to come up with a precise specification of the isomorphism 
between literals across different implementations and execution 
environment, so we allow maximum implementation flexibility and tell 
programmers not to depend on any particular mechanism.  But when 
everything is staying within the same runtime environment, the basic 
rules for how the reader works can apply.

Maybe this wasn't a good idea.  We worked hard to eliminate the 
differences that some earlier Lisp dialects had between the compiler and 
interpreter.  Having this difference between the file-compiler and 
in-core compiler seems like a wart.  As a result, it's likely that the 
following simple function will behave differently depending on whether 
it's compiled by COMPILE or COMPILE-FILE:

(defun compile-file-p ()
  "Should return NIL when COMPILEd, may return T when COMPILE-FILEd."
  (eq '(nil) '(nil)))

On the other hand, it generally takes some perverse programming for this 
to cause an issue with a real-world application, so it's a pretty minor 
issue.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: jayessay
Subject: Re: Destructive Functions
Date: 
Message-ID: <m37j9vf1x4.fsf@rigel.goldenthreadtech.com>
Barry Margolin <······@alum.mit.edu> writes:

> > I believe you are thinking of coalescing here.  Literals (objects) in
> > COMPILEd code are required to reference (as in eql) the literals
> > (objects) in the source code.  So, if a literal in the source is
> > already "coalesced", say by the reader, then the COMPILEd code will
> > refer to only one such object for that literal.  So, the thrust of
> > what Pascal is saying here still stands.
> 
> The reader is not allowed to coalesce constants, AFAIK.  Only the 
> file-compiler can.

Hence the "scare-quotes".  To coalesce literals X and Y from some
source code would mean that they must start out not eql, but their
corresponding objects in the compiled code are eql.  But if (eql X Y)
is true, then their corresponding objects in the compiled code of a
COMPILE must also be eql.  So, if '(1 2 3) shows up as a literal in
two pieces of some source, and these map to the same object, then they
are eql in the source, and so must be eql in the compiled code.
However, it seems clear now that even with the scare quotes, it was a
bad choice to use the term "coalesce" for this.


> in-core compiler seems like a wart.  As a result, it's likely that the 
> following simple function will behave differently depending on whether 
> it's compiled by COMPILE or COMPILE-FILE:
> 
> (defun compile-file-p ()
>   "Should return NIL when COMPILEd, may return T when COMPILE-FILEd."
>   (eq '(nil) '(nil)))

Interesting.  I would have thought otherwise.  Here's some data on this:

CL-USER(1): (defun foo () (eq '(1 2 3) '(1 2 3)))
FOO
CL-USER(2): (foo)
NIL ;; !!! a bit odd to me.
CL-USER(3): (compile 'foo)
FOO
NIL
NIL
CL-USER(4): (foo)
T ;;; More like it to my mind, but still odd given the interpreter results
CL-USER(5): (disassemble 'foo)
;; disassembly of #<Function FOO>
;; formals: 
;; constant vector:
0: (1 2 3)  ;; Looks right to me.

;; code start: #x7140a67c:
   0: e3 02       jcxz  4
   2: cd 61       int   $97             ; EXCL::TRAP-ARGERR
   4: 80 7f 97 00 cmpb  [edi-105],$0    ; SYS::C_INTERRUPT
   8: 74 02       jz    12
  10: cd 64       int   $100            ; EXCL::TRAP-SIGNAL-HIT
  12: 8b 5e 12    movl  ebx,[esi+18]    ; (1 2 3) [And here we see what I
  15: 3b 5e 12    cmpl  ebx,[esi+18]    ; (1 2 3)  would have expected anyway]
  18: 74 07       jz    27
  20: 8b c7       movl  eax,edi
  22: f8          clc
  23: 8b 75 fc    movl  esi,[ebp-4]
  26: c3          ret
  27: 8b 47 e7    movl  eax,[edi-25]    ; T
  30: f8          clc
  31: eb f6       jmp   23
  33: 90          nop
CL-USER(6): 



/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: http://public.xdi.org/=pf
Subject: Re: Destructive Functions
Date: 
Message-ID: <m2zmmqq3hy.fsf@mycroft.actrix.gen.nz>
On 24 Dec 2005 01:24:07 -0500, jayessay  wrote:

> Barry Margolin <······@alum.mit.edu> writes:
>> > I believe you are thinking of coalescing here.  Literals (objects) in
>> > COMPILEd code are required to reference (as in eql) the literals
>> > (objects) in the source code.  So, if a literal in the source is
>> > already "coalesced", say by the reader, then the COMPILEd code will
>> > refer to only one such object for that literal.  So, the thrust of
>> > what Pascal is saying here still stands.
>> 
>> The reader is not allowed to coalesce constants, AFAIK.  Only the 
>> file-compiler can.

> Hence the "scare-quotes".  To coalesce literals X and Y from some
> source code would mean that they must start out not eql, but their
> corresponding objects in the compiled code are eql.  But if (eql X Y)
> is true, then their corresponding objects in the compiled code of a
> COMPILE must also be eql.  So, if '(1 2 3) shows up as a literal in
> two pieces of some source, and these map to the same object, then they

The literal '(1 2 3) appearing twice (in two pieces of source) can't
"map to the same object", since the list has to be built up at read
time.  (Unless you mean something like using #n# notation to put the
same object in two places)

>> in-core compiler seems like a wart.  As a result, it's likely that the 
>> following simple function will behave differently depending on whether 
>> it's compiled by COMPILE or COMPILE-FILE:
>> 
>> (defun compile-file-p ()
>>   "Should return NIL when COMPILEd, may return T when COMPILE-FILEd."
>>   (eq '(nil) '(nil)))

> Interesting.  I would have thought otherwise.  Here's some data on this:

> CL-USER(1): (defun foo () (eq '(1 2 3) '(1 2 3)))
> FOO
> CL-USER(2): (foo)
> NIL ;; !!! a bit odd to me.

Evaluating (QUOTE x) returns x -- the very same value that occurs in
the QUOTE form, not some "similar" value.  The list (1 2 3) in the
first QUOTE form is obviously a different list than the one in the
second QUOTE form, so they /can't/ be EQ.

> CL-USER(3): (compile 'foo)
> FOO
> NIL
> NIL
> CL-USER(4): (foo)
> T ;;; More like it to my mind, but still odd given the interpreter results

Eh?  What implementation is this?  I'd call that a bug.


-- 
Quid enim est stultius quam incerta pro certis habere, falsa pro veris?
                                                                -- Cicero
(setq reply-to
  (concatenate 'string "Paul Foley " "<mycroft" '(··@) "actrix.gen.nz>"))
From: Duane Rettig
Subject: Re: Destructive Functions
Date: 
Message-ID: <o0hd8yfn8l.fsf@franz.com>
Paul Foley <···@below.invalid> (http://public.xdi.org/=pf) writes:

> On 24 Dec 2005 01:24:07 -0500, jayessay  wrote:
>
>> CL-USER(1): (defun foo () (eq '(1 2 3) '(1 2 3)))
>> FOO
>> CL-USER(2): (foo)
>> NIL ;; !!! a bit odd to me.
>
> Evaluating (QUOTE x) returns x -- the very same value that occurs in
> the QUOTE form, not some "similar" value.  The list (1 2 3) in the
> first QUOTE form is obviously a different list than the one in the
> second QUOTE form, so they /can't/ be EQ.
>
>> CL-USER(3): (compile 'foo)
>> FOO
>> NIL
>> NIL
>> CL-USER(4): (foo)
>> T ;;; More like it to my mind, but still odd given the interpreter results
>
> Eh?  What implementation is this?  I'd call that a bug.

It's probably Allegro CL 6.2 - I recognize the code - and it is
a bug.  7.0 does the right thing.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Pascal Bourguignon
Subject: Re: Destructive Functions
Date: 
Message-ID: <87hd8yesuu.fsf@thalassa.informatimago.com>
Paul Foley <···@below.invalid> (http://public.xdi.org/=pf) writes:
>>> in-core compiler seems like a wart.  As a result, it's likely that the 
>>> following simple function will behave differently depending on whether 
>>> it's compiled by COMPILE or COMPILE-FILE:
>>> 
>>> (defun compile-file-p ()
>>>   "Should return NIL when COMPILEd, may return T when COMPILE-FILEd."
>>>   (eq '(nil) '(nil)))
>
>> Interesting.  I would have thought otherwise.  Here's some data on this:
>
>> CL-USER(1): (defun foo () (eq '(1 2 3) '(1 2 3)))
>> FOO
>> CL-USER(2): (foo)
>> NIL ;; !!! a bit odd to me.
>
> Evaluating (QUOTE x) returns x -- the very same value that occurs in
> the QUOTE form, not some "similar" value.  The list (1 2 3) in the
> first QUOTE form is obviously a different list than the one in the
> second QUOTE form, so they /can't/ be EQ.
>
>> CL-USER(3): (compile 'foo)
>> FOO
>> NIL
>> NIL
>> CL-USER(4): (foo)
>> T ;;; More like it to my mind, but still odd given the interpreter results
>
> Eh?  What implementation is this?  I'd call that a bug.

No, it's a feature.  It's called literal folding.

For example, in C, when you have literal strings that are suffixes,
they can share the same storage:

char* p="hello world";
char* q="world";
/* You can have */ q==p+6
/* in addition to the warning of assigning a const char* to a char* */


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

WARNING: This product attracts every other piece of matter in the
universe, including the products of other manufacturers, with a
force proportional to the product of the masses and inversely
proportional to the distance between them.
From: Christophe Rhodes
Subject: Re: Destructive Functions
Date: 
Message-ID: <sqvexekexv.fsf@cam.ac.uk>
Pascal Bourguignon <····@mouse-potato.com> writes:

> Paul Foley <···@below.invalid> (http://public.xdi.org/=pf) writes:
>> Eh?  What implementation is this?  I'd call that a bug.
>
> No, it's a feature.  It's called literal folding.

No, it's a bug.  CLHS 3.2.4 states

  The functions eval and compile are required to ensure that literal
  objects referenced within the resulting interpreted or compiled code
  objects are the same as the corresponding objects in the source
  code. compile-file, on the other hand, must produce a compiled file
  that, when loaded with load, constructs the objects defined by the
  source code and produces references to them.

and

  The constraints on literal objects described in this section apply
  only to compile-file; eval and compile do not copy or coalesce
  constants.

So code processed by compile-file is allowed to coalesce constants, or
do "literal folding" as you call it, but code processed by compile, as
in the grandparent post, is not.

Christophe
From: http://public.xdi.org/=pf
Subject: Re: Destructive Functions
Date: 
Message-ID: <m2psnmpwz5.fsf@mycroft.actrix.gen.nz>
On Sat, 24 Dec 2005 10:39:53 +0100, Pascal Bourguignon wrote:

>>> CL-USER(4): (foo)
>>> T ;;; More like it to my mind, but still odd given the interpreter results
>> 
>> Eh?  What implementation is this?  I'd call that a bug.

> No, it's a feature.  It's called literal folding.

Yes, and it's fine for the file compiler to do that, but show me where
the in-core compiler is allowed to change the identity of objects!?
The two objects are not EQ going in, so they can't be EQ afterwards.
[Except for fixnums and characters, which don't (per the standard)
have proper identity anyway]

-- 
Quid enim est stultius quam incerta pro certis habere, falsa pro veris?
                                                                -- Cicero
(setq reply-to
  (concatenate 'string "Paul Foley " "<mycroft" '(··@) "actrix.gen.nz>"))
From: jayessay
Subject: Re: Destructive Functions
Date: 
Message-ID: <m3u0cydzvv.fsf@rigel.goldenthreadtech.com>
Paul Foley <···@below.invalid> (http://public.xdi.org/=pf) writes:

> The literal '(1 2 3) appearing twice (in two pieces of source) can't
> "map to the same object", since the list has to be built up at read
> time.

OK, in that case Barry's points all make sense.  I'm still a little
puzzled why a reader couldn't do this.  Must be something obvious that
I'm missing.  For example, you have some source:

(.... '(1 2 3) .... '(1 2 3) ...)

OK, the reader reads this all in from the starting paren to the ending
paren.  Along the way it is building up the internal representation.
What is it about the second literal that the reader can't recognize it
as equal to the first, and thus just have both parts of the rep point
to the same literal object?  Or have I just missed where the part in
the spec which simply states that you just can't have the reader doing
this, period, end of story?


> (Unless you mean something like using #n# notation to put the
> same object in two places)

Presumably this might in fact "do the job", but it wasn't what I was
thinking.


> > T ;;; More like it to my mind, but still odd given the interpreter results
> 
> Eh?  What implementation is this?  I'd call that a bug.

Yep, bug.


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Barry Margolin
Subject: Re: Destructive Functions
Date: 
Message-ID: <barmar-0A01B8.19375724122005@comcast.dca.giganews.com>
In article <··············@rigel.goldenthreadtech.com>,
 jayessay <······@foo.com> wrote:

> Paul Foley <···@below.invalid> (http://public.xdi.org/=pf) writes:
> 
> > The literal '(1 2 3) appearing twice (in two pieces of source) can't
> > "map to the same object", since the list has to be built up at read
> > time.
> 
> OK, in that case Barry's points all make sense.  I'm still a little
> puzzled why a reader couldn't do this.  Must be something obvious that
> I'm missing.  For example, you have some source:
> 
> (.... '(1 2 3) .... '(1 2 3) ...)
> 
> OK, the reader reads this all in from the starting paren to the ending
> paren.  Along the way it is building up the internal representation.
> What is it about the second literal that the reader can't recognize it
> as equal to the first, and thus just have both parts of the rep point
> to the same literal object?  Or have I just missed where the part in
> the spec which simply states that you just can't have the reader doing
> this, period, end of story?

I can't find it now, but I'm pretty sure that somewhere in the 
description of the Lisp reader it says that it always returns a fresh 
list when it reads the printed representation of a list.  This includes 
the nested reads that occur for the internal lists.

Is there a search engine for the Hyperspec?

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: ········@gmail.com
Subject: Re: Destructive Functions
Date: 
Message-ID: <1135492939.297524.111790@g43g2000cwa.googlegroups.com>
Barry Margolin wrote:
> Is there a search engine for the Hyperspec?

Have you tried:
http://www.franz.com/search/

--
Bill Clementson
From: Barry Margolin
Subject: Re: Destructive Functions
Date: 
Message-ID: <barmar-BFE7B7.23511425122005@comcast.dca.giganews.com>
In article <························@g43g2000cwa.googlegroups.com>,
 ········@gmail.com wrote:

> Barry Margolin wrote:
> > Is there a search engine for the Hyperspec?
> 
> Have you tried:
> http://www.franz.com/search/

Unfortunately, they've included the glossary in their index, with each 
letter of the alphabet as a single page.  This really screws up the the 
matches, because it words in unrelated glossary entries will cause the 
whole page to get a good score.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Pascal Bourguignon
Subject: Re: Destructive Functions
Date: 
Message-ID: <878xu9dmc4.fsf@thalassa.informatimago.com>
Barry Margolin <······@alum.mit.edu> writes:
> Is there a search engine for the Hyperspec?

http://www.google.com/search?q=site%3awww.lispworks.com%2fdocumentation%2fHyperSpec+car


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

HEALTH WARNING: Care should be taken when lifting this product,
since its mass, and thus its weight, is dependent on its velocity
relative to the user.
From: Duane Rettig
Subject: Re: Destructive Functions
Date: 
Message-ID: <o0oe32ga7u.fsf@franz.com>
Pascal Bourguignon <····@mouse-potato.com> writes:

> Barry Margolin <······@alum.mit.edu> writes:
>> Is there a search engine for the Hyperspec?
>
> http://www.google.com/search?q=site%3awww.lispworks.com%2fdocumentation%2fHyperSpec+car

Also,

http://www.franz.com/search/index.lhtml#ansispec

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Lars Brinkhoff
Subject: Re: Destructive Functions
Date: 
Message-ID: <85wthjlyy7.fsf@junk.nocrew.org>
Pascal Bourguignon <····@mouse-potato.com> writes:
> Barry Margolin <······@alum.mit.edu> writes:
>> Is there a search engine for the Hyperspec?
> http://www.google.com/search?q=site%3awww.lispworks.com%2fdocumentation%2fHyperSpec+car

There is a copy of the HyperSpec at http://clhs.lisp.se/, but Google
doesn't index it very well.
From: jayessay
Subject: Re: Destructive Functions
Date: 
Message-ID: <m3psnie2xc.fsf@rigel.goldenthreadtech.com>
Barry Margolin <······@alum.mit.edu> writes:

> In article <··············@rigel.goldenthreadtech.com>,
>  jayessay <······@foo.com> wrote:
> 
> > Paul Foley <···@below.invalid> (http://public.xdi.org/=pf) writes:
> > 
> > > The literal '(1 2 3) appearing twice (in two pieces of source) can't
> > > "map to the same object", since the list has to be built up at read
> > > time.
> > 
> > OK, in that case Barry's points all make sense.  I'm still a little
> > puzzled why a reader couldn't do this.  Must be something obvious that
> > I'm missing.  For example, you have some source:
> > 
> > (.... '(1 2 3) .... '(1 2 3) ...)
> > 
> > OK, the reader reads this all in from the starting paren to the ending
> > paren.  Along the way it is building up the internal representation.
> > What is it about the second literal that the reader can't recognize it
> > as equal to the first, and thus just have both parts of the rep point
> > to the same literal object?  Or have I just missed where the part in
> > the spec which simply states that you just can't have the reader doing
> > this, period, end of story?
> 
> I can't find it now, but I'm pretty sure that somewhere in the 
> description of the Lisp reader it says that it always returns a fresh 
> list when it reads the printed representation of a list.  This includes 
> the nested reads that occur for the internal lists.

Ah, OK.  Though I haven't yet found that bit yet either.  If I find it
I will post; if you, or Duane, find or know where it is, please post
here as well.  Thanks,


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: jayessay
Subject: Re: Destructive Functions
Date: 
Message-ID: <m3hd8udowr.fsf@rigel.goldenthreadtech.com>
jayessay <······@foo.com> writes:

> Barry Margolin <······@alum.mit.edu> writes:
> 
> > In article <··············@rigel.goldenthreadtech.com>,
> >  jayessay <······@foo.com> wrote:
...
> > > I'm missing.  For example, you have some source:
> > > 
> > > (.... '(1 2 3) .... '(1 2 3) ...)
> > > 
> > > OK, the reader reads this all in from the starting paren to the ending
> > > paren.  Along the way it is building up the internal representation.
> > > What is it about the second literal that the reader can't recognize it
> > > as equal to the first, and thus just have both parts of the rep point
> > > to the same literal object?  Or have I just missed where the part in
> > > the spec which simply states that you just can't have the reader doing
> > > this, period, end of story?
> > 
> > I can't find it now, but I'm pretty sure that somewhere in the 
> > description of the Lisp reader it says that it always returns a fresh 
> > list when it reads the printed representation of a list.  This includes 
> > the nested reads that occur for the internal lists.
> 
> Ah, OK.  Though I haven't yet found that bit yet either.  If I find it
> I will post; if you, or Duane, find or know where it is, please post
> here as well.  Thanks,

OK, I'm not convinced I've found this (see one possibility below) and
am giving up.  In fact the only two bits that seem to actually
specifically speak to this seem to leave open the possibility that the
literals could be identical:


2.4.1 Left-Paren reader macro defintion:

"The left-parenthesis initiates reading of a list. read is called
recursively to read successive objects until a right parenthesis is
found in the input stream. A list of the objects read is
returned."

Doesn't say a _freshly consed up_ list of the objects is returned.


23.2, the entry for READ:

"read parses the printed representation of an object from
input-stream and builds such an object."

and later:

"return the object read from input-stream."

These two pieces provide some indication that 1) something new is made
("_builds_ such an object", emphasis added) and 2) "return the object
read" may mean the one that was newly built.

But, the object read (in this case) is from the
(-reader-macro-function which as indicated above doesn't say the list
must be freshly consed.

Steele also talks about this a bit (beyond what got into the ANSI
spec.), and indicates that having the reader return identical objects
in these sort of cases is in practice difficult and not always
desirable.


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Barry Margolin
Subject: Re: Destructive Functions
Date: 
Message-ID: <barmar-0D204B.20390127122005@comcast.dca.giganews.com>
In article <··············@rigel.goldenthreadtech.com>,
 jayessay <······@foo.com> wrote:

> 2.4.1 Left-Paren reader macro defintion:
> 
> "The left-parenthesis initiates reading of a list. read is called
> recursively to read successive objects until a right parenthesis is
> found in the input stream. A list of the objects read is
> returned."
> 
> Doesn't say a _freshly consed up_ list of the objects is returned.

Yeah, that's where I was hoping to find it, and was unhappy that it 
doesn't say "fresh list".

> 
> 
> 23.2, the entry for READ:
> 
> "read parses the printed representation of an object from
> input-stream and builds such an object."
> 
> and later:
> 
> "return the object read from input-stream."
> 
> These two pieces provide some indication that 1) something new is made
> ("_builds_ such an object", emphasis added) and 2) "return the object
> read" may mean the one that was newly built.

Except that there are some common cases where it *doesn't* return 
something new.  Most obvious is when it's reading the representation of 
a symbol, it will return an existing interned symbol when possible.

I wonder if there's a general statement somewhere that functions return 
fresh objects unless the description specifically says that it may 
return an existing object.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: http://public.xdi.org/=pf
Subject: Re: Destructive Functions
Date: 
Message-ID: <m24q4vowab.fsf@mycroft.actrix.gen.nz>
On 24 Dec 2005 15:05:40 -0500, jayessay  wrote:

> Paul Foley <···@below.invalid> (http://public.xdi.org/=pf) writes:
>> The literal '(1 2 3) appearing twice (in two pieces of source) can't
>> "map to the same object", since the list has to be built up at read
>> time.

> OK, in that case Barry's points all make sense.  I'm still a little
> puzzled why a reader couldn't do this.  Must be something obvious that
> I'm missing.  For example, you have some source:

> (.... '(1 2 3) .... '(1 2 3) ...)

> OK, the reader reads this all in from the starting paren to the ending
> paren.  Along the way it is building up the internal representation.

It hits the first embedded list, makes a recursive call to read the
list, and gets the resulting object.  When it reads the second
embedded list, the recursive call can't know in advance that it's
going to see a similar list, so it has to build up a new list, right?
Having done that, it doesn't know what the higher-level call has seen,
so it can't notice that this list is similar to the previous one, so
it just returns it.  The outer call would then have to examine it to
see if it's similar to the previous one, and replace it.  But the
outer call doesn't know the source: it needn't have come from a
literal list; you could have put something like #.*foo* in there, but
replacing /that/ would be very weird: surely the resulting list should
be EQ to *foo*!


-- 
Quid enim est stultius quam incerta pro certis habere, falsa pro veris?
                                                                -- Cicero
(setq reply-to
  (concatenate 'string "Paul Foley " "<mycroft" '(··@) "actrix.gen.nz>"))
From: Sam Steingold
Subject: Re: Destructive Functions
Date: 
Message-ID: <u8xub3nbv.fsf@gnu.org>
> *  <······@tznvy.pbz> [2005-12-22 23:22:47 -0800]:
>
> I had a question I was hoping someone could help me with.  I'm writing
> a program where I need to parse this list, but it makes things a lot
> easier if I pass it the list in reverse order and some NILs appended to
> either side.  Since the lists I'm dealing with are quite long, I wanted
> to try to make the code as efficient as possible.  What I tried to do
> was this:
>
> (defun fixlist (alst)
>   (nreverse (nconc '(NIL)
> 		   '(NIL)
> 		   '(NIL)
> 		   '(NIL)
> 		   (copy-list alst)
> 		   '(NIL)
> 		   '(NIL)
> 		   '(NIL))))
>
> This code works neither in clisp nor in openmcl.  Or rather, it works
> the first time after I load it and then hangs when I try to call it
> again.

self-modified code is not a very good idea.
http://clisp.cons.org/impnotes/faq.html#faq-self-mod

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
http://www.honestreporting.com http://www.savegushkatif.org http://ffii.org/
http://www.dhimmi.com/ http://www.openvotingconsortium.org/
"Syntactic sugar causes cancer of the semicolon."	-Alan Perlis
From: Christophe Rhodes
Subject: Re: Destructive Functions
Date: 
Message-ID: <sqvexgkt6g.fsf@cam.ac.uk>
······@gmail.com writes:

> I was wondering if anyone could please exlpain to what problems the
> destructive functions are causing.  As far as I can tell I'm only
> modifying cons structures I've just created so I thought it would be
> okay to use the destructive functions to save time.  Thanks!

The message that SBCL produces on your code is:

; in: LAMBDA NIL
;     (NCONC '(NIL) '(NIL) '(NIL) '(NIL) (COPY-LIST ALST) '(NIL) '(NIL) '(NIL))
;
; caught WARNING:
;   Destructive function NCONC called on constant data.
;   See also:
;     The ANSI Standard, Special Operator QUOTE
;     The ANSI Standard, Section 3.2.2.3

I've seen that you've understood what is happening, so my question is
whether seeing this message would have helped you find out earlier
what was going wrong.

Christophe