unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* replacing a certain element in a list with another
@ 2003-09-30  8:38 Klaus Berndl
  2003-09-30  9:05 ` David Kastrup
  2003-09-30 14:16 ` Stefan Monnier
  0 siblings, 2 replies; 27+ messages in thread
From: Klaus Berndl @ 2003-09-30  8:38 UTC (permalink / raw)



Suppose i have the following list:

'(a b c d)

What is a good way to replace one of the list-elements with another, so foe
example replacing the 'c with 'e?

But: i do not want using any c-functions, so i would prefer a solution without
using `substitute'!

Is the solution easier if i always want to replace the last element of the
list?

I think so, because it could be:

(defvar my-list '( a b c d))

(let ((temp-l (nreverse my-list)))
  (setcar temp-l 'e)
  (nreverse temp-l))

Is this a good elisp-solution? 

Thanks for help,
Klaus
 
-- 
Klaus Berndl			mailto: klaus.berndl@sdm.de
sd&m AG				http://www.sdm.de
software design & management	
Thomas-Dehler-Str. 27, 81737 München, Germany
Tel +49 89 63812-392, Fax -220

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30  8:38 replacing a certain element in a list with another Klaus Berndl
@ 2003-09-30  9:05 ` David Kastrup
  2003-09-30  9:59   ` Klaus Berndl
  2003-09-30 14:16 ` Stefan Monnier
  1 sibling, 1 reply; 27+ messages in thread
From: David Kastrup @ 2003-09-30  9:05 UTC (permalink / raw)


Klaus Berndl <klaus.berndl@sdm.de> writes:

> Suppose i have the following list:
> 
> '(a b c d)
> 
> What is a good way to replace one of the list-elements with another, so foe
> example replacing the 'c with 'e?

> But: i do not want using any c-functions, so i would prefer a
> solution without using `substitute'!

Uh, what?

Anyhow, try

(let ((xxx '(a b c d)))
   (setcar (member 'c xxx) 'e)
   xxx)

> Is the solution easier if i always want to replace the last element
> of the list?

Not really.

> I think so, because it could be:
> 
> (defvar my-list '( a b c d))
> 
> (let ((temp-l (nreverse my-list)))
>   (setcar temp-l 'e)
>   (nreverse temp-l))
> 
> Is this a good elisp-solution? 

No.  Runs through the list quite more often than necessary, and
leaves my-list in a pretty undefined state.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30  9:05 ` David Kastrup
@ 2003-09-30  9:59   ` Klaus Berndl
  2003-09-30 10:03     ` David Kastrup
  2003-09-30 12:12     ` Pascal Bourguignon
  0 siblings, 2 replies; 27+ messages in thread
From: Klaus Berndl @ 2003-09-30  9:59 UTC (permalink / raw)


On 30 Sep 2003, David Kastrup wrote:

>  Klaus Berndl <klaus.berndl@sdm.de> writes:
>  
> > Suppose i have the following list:
> > 
> > '(a b c d)
> > 
> > What is a good way to replace one of the list-elements with another, so
> > foe example replacing the 'c with 'e?
>  
> > But: i do not want using any c-functions, so i would prefer a
> > solution without using `substitute'!
>  
>  Uh, what?

This comes from a recommendation in the elisp-info-manual (Standards -->
Coding conventions"):

   * Please don't require the `cl' package of Common Lisp extensions at
     run time.  Use of this package is optional, and it is not part of
     the standard Emacs namespace.  If your package loads `cl' at run
     time, that could cause name clashes for users who don't use that
     package.

     However, there is no problem with using the `cl' package at compile
     time, for the sake of macros.  You do that like this:

          (eval-when-compile (require 'cl))

I interpret this ("...for the sake of macros...") so, that at least for
packages for GNU Emacs the code can use cl-macros but should not use any
functions from the cl package. Please correct me if i have misunderstood here
something!?

>  
>  Anyhow, try
>  
>  (let ((xxx '(a b c d)))
>     (setcar (member 'c xxx) 'e)
>     xxx)

Thanks a lot, David!

Ciao,
Klaus

-- 
Klaus Berndl			mailto: klaus.berndl@sdm.de
sd&m AG				http://www.sdm.de
software design & management	
Thomas-Dehler-Str. 27, 81737 München, Germany
Tel +49 89 63812-392, Fax -220

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30  9:59   ` Klaus Berndl
@ 2003-09-30 10:03     ` David Kastrup
  2003-09-30 10:19       ` Klaus Berndl
  2003-09-30 12:12     ` Pascal Bourguignon
  1 sibling, 1 reply; 27+ messages in thread
From: David Kastrup @ 2003-09-30 10:03 UTC (permalink / raw)


Klaus Berndl <klaus.berndl@sdm.de> writes:

> On 30 Sep 2003, David Kastrup wrote:
> 
> >  Klaus Berndl <klaus.berndl@sdm.de> writes:
> >  
> > > Suppose i have the following list:
> > > 
> > > '(a b c d)
> > > 
> > > What is a good way to replace one of the list-elements with another, so
> > > foe example replacing the 'c with 'e?
> >  
> > > But: i do not want using any c-functions, so i would prefer a
> > > solution without using `substitute'!
> >  
> >  Uh, what?
> 
> This comes from a recommendation in the elisp-info-manual (Standards -->
> Coding conventions"):
> 
>    * Please don't require the `cl' package of Common Lisp extensions
>    at run time.

What do c-functions have to do with cl?

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30 10:03     ` David Kastrup
@ 2003-09-30 10:19       ` Klaus Berndl
  0 siblings, 0 replies; 27+ messages in thread
From: Klaus Berndl @ 2003-09-30 10:19 UTC (permalink / raw)


On 30 Sep 2003, David Kastrup wrote:

>  Klaus Berndl <klaus.berndl@sdm.de> writes:
>  
> > On 30 Sep 2003, David Kastrup wrote:
> > 
> > >  Klaus Berndl <klaus.berndl@sdm.de> writes:
> > >  
> > > > Suppose i have the following list:
> > > > 
> > > > '(a b c d)
> > > > 
> > > > What is a good way to replace one of the list-elements with another,
> > > > so foe example replacing the 'c with 'e?
> > >  
> > > > But: i do not want using any c-functions, so i would prefer a
                                     ^
  should be cl ----------------------´                                    


> > > > solution without using `substitute'!
> > >  
> > >  Uh, what?
> > 
> > This comes from a recommendation in the elisp-info-manual (Standards -->
> > Coding conventions"):
> > 
> >    * Please don't require the `cl' package of Common Lisp extensions
> >    at run time.
>  
>  What do c-functions have to do with cl?

Hoops, sorry, my fault, see above: I meant cl-functions, i.e. functions of
the cl-package! Was only a typo but with complete misleading result ;-)

Klaus

-- 
Klaus Berndl			mailto: klaus.berndl@sdm.de
sd&m AG				http://www.sdm.de
software design & management	
Thomas-Dehler-Str. 27, 81737 München, Germany
Tel +49 89 63812-392, Fax -220

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30  9:59   ` Klaus Berndl
  2003-09-30 10:03     ` David Kastrup
@ 2003-09-30 12:12     ` Pascal Bourguignon
  2003-09-30 14:14       ` Stefan Monnier
  1 sibling, 1 reply; 27+ messages in thread
From: Pascal Bourguignon @ 2003-09-30 12:12 UTC (permalink / raw)



Klaus Berndl <klaus.berndl@sdm.de> writes:
>    * Please don't require the `cl' package of Common Lisp extensions at
>      run time.  Use of this package is optional, and it is not part of
>      the standard Emacs namespace.  If your package loads `cl' at run
>      time, that could cause name clashes for users who don't use that
>      package.

Yeah!   Great!  So  when I'll  distribute  my packages,  I'll have  to
include the whole cl inside  it (nicely prefixing all the symbols with
a 'pjb-cl::'). 

Wouldn't  it be  simplier if  emacs  lisp implemented  a true  PACKAGE
system (name spaces) like Common-Lisp?


-- 
__Pascal_Bourguignon__
http://www.informatimago.com/
Do not adjust your mind, there is a fault in reality.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30 12:12     ` Pascal Bourguignon
@ 2003-09-30 14:14       ` Stefan Monnier
  2003-09-30 14:26         ` Klaus Berndl
  0 siblings, 1 reply; 27+ messages in thread
From: Stefan Monnier @ 2003-09-30 14:14 UTC (permalink / raw)


> Yeah!   Great!  So  when I'll  distribute  my packages,  I'll have  to
> include the whole cl inside  it (nicely prefixing all the symbols with
> a 'pjb-cl::'). 

The text only applies to packages bundled with Emacs.
I.e. I don't use CL function in PCL-CVS (which comes with Emacs-21),
but I very happily use them in sml-mode (which is not part of Emacs).


        Stefan

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30  8:38 replacing a certain element in a list with another Klaus Berndl
  2003-09-30  9:05 ` David Kastrup
@ 2003-09-30 14:16 ` Stefan Monnier
  2003-09-30 14:28   ` Klaus Berndl
  1 sibling, 1 reply; 27+ messages in thread
From: Stefan Monnier @ 2003-09-30 14:16 UTC (permalink / raw)


> Suppose i have the following list:
> '(a b c d)
> What is a good way to replace one of the list-elements with another, so foe
> example replacing the 'c with 'e?

    (mapcar (lambda (x) (if (eq x 'c) 'e x)) <list>)

I'd advise against using `setcar/setcdr' unless you have good reasons to
do it.


        Stefan

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30 14:14       ` Stefan Monnier
@ 2003-09-30 14:26         ` Klaus Berndl
  0 siblings, 0 replies; 27+ messages in thread
From: Klaus Berndl @ 2003-09-30 14:26 UTC (permalink / raw)


On Tue, 30 Sep 2003, Stefan Monnier wrote:

> > Yeah!   Great!  So  when I'll  distribute  my packages,  I'll have  to
> > include the whole cl inside  it (nicely prefixing all the symbols with
> > a 'pjb-cl::'). 
>  
>  The text only applies to packages bundled with Emacs.
>  I.e. I don't use CL function in PCL-CVS (which comes with Emacs-21),
>  but I very happily use them in sml-mode (which is not part of Emacs).

OK, well, but i i'm writing and maintaining a package which could be become
part of Emacs in future, then i'm not keen on changing my whole code and
replacing all my cl-functions (used before becoming part of Emacs) with
equivalent constructs.

Maybe the whole cl-package should be rewritten by adding to all functions and
macros the cl- prefix....and a deprecated alias to the current names?!

Klaus

>  
>  
>          Stefan

-- 
Klaus Berndl			mailto: klaus.berndl@sdm.de
sd&m AG				http://www.sdm.de
software design & management	
Thomas-Dehler-Str. 27, 81737 München, Germany
Tel +49 89 63812-392, Fax -220

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30 14:16 ` Stefan Monnier
@ 2003-09-30 14:28   ` Klaus Berndl
  2003-09-30 15:03     ` Stefan Monnier
  0 siblings, 1 reply; 27+ messages in thread
From: Klaus Berndl @ 2003-09-30 14:28 UTC (permalink / raw)


On Tue, 30 Sep 2003, Stefan Monnier wrote:



> > Suppose i have the following list: '(a b c d) What is a good way to
> > replace one of the list-elements with another, so foe example replacing
> > the 'c with 'e?
>  
>      (mapcar (lambda (x) (if (eq x 'c) 'e x)) <list>)
>  
>  I'd advise against using `setcar/setcdr' unless you have good reasons to
>  do it.

Why? I believe, but just for my interest and to become a better
elisp-programmer?!

Thanks,
Klaus

>  
>  
>          Stefan

-- 
Klaus Berndl			mailto: klaus.berndl@sdm.de
sd&m AG				http://www.sdm.de
software design & management	
Thomas-Dehler-Str. 27, 81737 München, Germany
Tel +49 89 63812-392, Fax -220

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30 14:28   ` Klaus Berndl
@ 2003-09-30 15:03     ` Stefan Monnier
  2003-09-30 15:30       ` Kevin Rodgers
  0 siblings, 1 reply; 27+ messages in thread
From: Stefan Monnier @ 2003-09-30 15:03 UTC (permalink / raw)


>> I'd advise against using `setcar/setcdr' unless you have good reasons to
>> do it.
> Why? I believe, but just for my interest and to become a better
> elisp-programmer?!

Saves you from having to worry about what happens to "the old list".


        Stefan

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30 15:03     ` Stefan Monnier
@ 2003-09-30 15:30       ` Kevin Rodgers
  2003-09-30 15:47         ` Stefan Monnier
  0 siblings, 1 reply; 27+ messages in thread
From: Kevin Rodgers @ 2003-09-30 15:30 UTC (permalink / raw)


Stefan Monnier wrote:

>>>I'd advise against using `setcar/setcdr' unless you have good reasons to
>>>do it.
>>
>>Why? I believe, but just for my interest and to become a better
>>elisp-programmer?!
> 
> Saves you from having to worry about what happens to "the old list".

Well, it depends on whether the OP wants to return a new list or to modify the
original list.

-- 
Kevin Rodgers

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30 15:30       ` Kevin Rodgers
@ 2003-09-30 15:47         ` Stefan Monnier
  2003-09-30 18:27           ` Roland Winkler
  0 siblings, 1 reply; 27+ messages in thread
From: Stefan Monnier @ 2003-09-30 15:47 UTC (permalink / raw)


> Well, it depends on whether the OP wants to return a new list or to modify
> the original list.

That's exactly what was meant by "have good reasons to do it".  Mixing the
in-place-update style with the create-new-stuff style (aka imperative style
vs functional style) is a common source of error because it generally makes
the code more "subtle" (more difficult to understand).  Since elisp usually
copies things around, inplace-update operations such as nconc, nreverse,
setcar, setcdr, delete, delq, ... should be used with caution.


        Stefan

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30 15:47         ` Stefan Monnier
@ 2003-09-30 18:27           ` Roland Winkler
  2003-09-30 20:01             ` Barry Margolin
  2003-10-16 20:52             ` Kai Grossjohann
  0 siblings, 2 replies; 27+ messages in thread
From: Roland Winkler @ 2003-09-30 18:27 UTC (permalink / raw)


Stefan Monnier <monnier@iro.umontreal.ca> writes:

> > Well, it depends on whether the OP wants to return a new list or to modify
> > the original list.
> 
> That's exactly what was meant by "have good reasons to do it".  Mixing the
> in-place-update style with the create-new-stuff style (aka imperative style
> vs functional style) is a common source of error because it generally makes
> the code more "subtle" (more difficult to understand).  Since elisp usually
> copies things around, inplace-update operations such as nconc, nreverse,
> setcar, setcdr, delete, delq, ... should be used with caution.

Kind of a related question:

The function `reverse' does not alter the original argument LIST. On
the other hand, `nreverse' reverses LIST by modifying cdr pointers.
Why does the docstring of `reverse' say

  See also the function `nreverse', which is used more often.

Yet, the info page for `nreverse' says

  To avoid confusion, we usually store the result of `nreverse' back
  in the same variable which held the original list:

Wouldn't it then be more natural to use `reverse' from the
beginning? Or am I missing something here??

Roland

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30 18:27           ` Roland Winkler
@ 2003-09-30 20:01             ` Barry Margolin
  2003-10-16 20:52             ` Kai Grossjohann
  1 sibling, 0 replies; 27+ messages in thread
From: Barry Margolin @ 2003-09-30 20:01 UTC (permalink / raw)


In article <m3u16u5dyn.fsf@tfkp07.physik.uni-erlangen.de>,
Roland Winkler  <Roland.Winkler@physik.uni-erlangen.de> wrote:
>Kind of a related question:
>
>The function `reverse' does not alter the original argument LIST. On
>the other hand, `nreverse' reverses LIST by modifying cdr pointers.
>Why does the docstring of `reverse' say
>
>  See also the function `nreverse', which is used more often.

One of the most common uses of reversing a list is part of the idiom for
accumulating values during a loop, e.g.

(let ((result nil))
  (dotimes (i 10)
    (push i result))
  (nreverse result))

Since this is a newly constructed list that has no other references to it,
it's fine to reverse it destructively rather than waste space creating a
new list.

>Yet, the info page for `nreverse' says
>
>  To avoid confusion, we usually store the result of `nreverse' back
>  in the same variable which held the original list:
>
>Wouldn't it then be more natural to use `reverse' from the
>beginning? Or am I missing something here??

You have to do the assignment whether you use reverse or nreverse.

-- 
Barry Margolin, barry.margolin@level3.com
Level(3), Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-09-30 18:27           ` Roland Winkler
  2003-09-30 20:01             ` Barry Margolin
@ 2003-10-16 20:52             ` Kai Grossjohann
  2003-10-22 20:06               ` Roland Winkler
  1 sibling, 1 reply; 27+ messages in thread
From: Kai Grossjohann @ 2003-10-16 20:52 UTC (permalink / raw)


Roland Winkler <Roland.Winkler@physik.uni-erlangen.de> writes:

> The function `reverse' does not alter the original argument LIST. On
> the other hand, `nreverse' reverses LIST by modifying cdr pointers.
> Why does the docstring of `reverse' say
>
>   See also the function `nreverse', which is used more often.
>
> Yet, the info page for `nreverse' says
>
>   To avoid confusion, we usually store the result of `nreverse' back
>   in the same variable which held the original list:
>
> Wouldn't it then be more natural to use `reverse' from the
> beginning? Or am I missing something here??

Well, (nreverse x) does destructively modify the list x, but
afterwards the value if x is not what you think:

*** Welcome to IELM ***  Type (describe-mode) for help.
ELISP> (setq x (list 1 2 3 4))
(1 2 3 4)

ELISP> (nreverse x)
(4 3 2 1)

ELISP> x
(1)

ELISP> 

Clear?

Kai

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-10-16 20:52             ` Kai Grossjohann
@ 2003-10-22 20:06               ` Roland Winkler
  2003-10-22 20:32                 ` Barry Margolin
  0 siblings, 1 reply; 27+ messages in thread
From: Roland Winkler @ 2003-10-22 20:06 UTC (permalink / raw)


Kai Grossjohann <kai.grossjohann@gmx.net> writes:
> Well, (nreverse x) does destructively modify the list x, but
> afterwards the value if x is not what you think:
> 
> *** Welcome to IELM ***  Type (describe-mode) for help.
> ELISP> (setq x (list 1 2 3 4))
> (1 2 3 4)
> 
> ELISP> (nreverse x)
> (4 3 2 1)
> 
> ELISP> x
> (1)
> 
> ELISP> 
> 
> Clear?

...not really  :-)

I tried to understand the docstring and the info page. However, I
could not really make use of it. So what is it that nreverse is
doing with its argument? And when is this useful??

Thanks,

Roland

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-10-22 20:06               ` Roland Winkler
@ 2003-10-22 20:32                 ` Barry Margolin
  2003-10-23 12:46                   ` Roland Winkler
  0 siblings, 1 reply; 27+ messages in thread
From: Barry Margolin @ 2003-10-22 20:32 UTC (permalink / raw)


In article <m3k76xf34y.fsf@tfkp07.physik.uni-erlangen.de>,
Roland Winkler  <Roland.Winkler@physik.uni-erlangen.de> wrote:
>Kai Grossjohann <kai.grossjohann@gmx.net> writes:
>> Well, (nreverse x) does destructively modify the list x, but
>> afterwards the value if x is not what you think:
>> 
>> *** Welcome to IELM ***  Type (describe-mode) for help.
>> ELISP> (setq x (list 1 2 3 4))
>> (1 2 3 4)
>> 
>> ELISP> (nreverse x)
>> (4 3 2 1)
>> 
>> ELISP> x
>> (1)
>> 
>> ELISP> 
>> 
>> Clear?
>
>...not really  :-)
>
>I tried to understand the docstring and the info page. However, I
>could not really make use of it. So what is it that nreverse is
>doing with its argument? And when is this useful??

When you start, you have the following:

Cell A: car = 1
        cdr = reference to Cell B
Cell B: car = 2
        cdr = reference to Cell C
Cell C: car = 3
        cdr = reference to Cell D
Cell D: car = 4
        cdr = nil
x's value cell = reference to Cell A

When you call nreverse, it is passed the contents of x's value cell,
i.e. the reference to Cell A.  It reverses the list by keeping all the
car's the same, but reversing the cdr links; this changes things to:

Cell A: car = 1
        cdr = nil
Cell B: car = 2
        cdr = reference to Cell A
Cell C: car = 3
        cdr = reference to Cell B
Cell D: car = 4
        cdr = reference to Cell C

Now the first cons in the reversed list is Cell D, and nreverse returns
this as its value.

But x's value cell still contains a reference to Cell A, which has become
the last cons in the chain.  So when you print it, you just see the
1-element list containing the last element of the reversed list.

Why is it done this way?  Because this is the simplest way to reverse a
list in place.  It can just step through the list, replacing each cdr with
a reference to the preceding cons cell.  This is much easier than swapping
all the car's in order to keep the order of the conses intact.

-- 
Barry Margolin, barry.margolin@level3.com
Level(3), Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-10-22 20:32                 ` Barry Margolin
@ 2003-10-23 12:46                   ` Roland Winkler
  2003-10-23 14:25                     ` Stefan Monnier
  2003-10-23 15:18                     ` Barry Margolin
  0 siblings, 2 replies; 27+ messages in thread
From: Roland Winkler @ 2003-10-23 12:46 UTC (permalink / raw)


Barry Margolin <barry.margolin@level3.com> writes:

> When you start, you have the following:
> 
> Cell A: car = 1
>         cdr = reference to Cell B
> Cell B: car = 2
>         cdr = reference to Cell C
> Cell C: car = 3
>         cdr = reference to Cell D
> Cell D: car = 4
>         cdr = nil
> x's value cell = reference to Cell A
> 
> When you call nreverse, it is passed the contents of x's value cell,
> i.e. the reference to Cell A.  It reverses the list by keeping all the
> car's the same, but reversing the cdr links; this changes things to:
> 
> Cell A: car = 1
>         cdr = nil
> Cell B: car = 2
>         cdr = reference to Cell A
> Cell C: car = 3
>         cdr = reference to Cell B
> Cell D: car = 4
>         cdr = reference to Cell C
> 
> Now the first cons in the reversed list is Cell D, and nreverse returns
> this as its value.
> 
> But x's value cell still contains a reference to Cell A, which has become
> the last cons in the chain.  So when you print it, you just see the
> 1-element list containing the last element of the reversed list.
> 
> Why is it done this way?  Because this is the simplest way to reverse a
> list in place.  It can just step through the list, replacing each cdr with
> a reference to the preceding cons cell.  This is much easier than swapping
> all the car's in order to keep the order of the conses intact.

Thank you very much!

It might be helpful to add a comment to the docstring or info page
for nreverse saying that its argument is modified such that
afterwards it is a 1-element list containing the last element of the
reversed list.

Roland

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-10-23 12:46                   ` Roland Winkler
@ 2003-10-23 14:25                     ` Stefan Monnier
  2003-10-23 15:30                       ` Kevin Rodgers
  2003-10-23 15:18                     ` Barry Margolin
  1 sibling, 1 reply; 27+ messages in thread
From: Stefan Monnier @ 2003-10-23 14:25 UTC (permalink / raw)


> It might be helpful to add a comment to the docstring or info page
> for nreverse saying that its argument is modified such that
> afterwards it is a 1-element list containing the last element of the
> reversed list.

I don't think this particular aspect of the behavior should be documented.
Maybe we should add a note saying "the argument should not be used
afterwards", but even that would not be very convincing.
I think the only reasonable thing to put is a "don't use this unless you
know what you're doing".


        Stefan

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-10-23 12:46                   ` Roland Winkler
  2003-10-23 14:25                     ` Stefan Monnier
@ 2003-10-23 15:18                     ` Barry Margolin
  2003-10-23 22:03                       ` Roland Winkler
  1 sibling, 1 reply; 27+ messages in thread
From: Barry Margolin @ 2003-10-23 15:18 UTC (permalink / raw)


In article <m3u160cea8.fsf@tfkp07.physik.uni-erlangen.de>,
Roland Winkler  <Roland.Winkler@physik.uni-erlangen.de> wrote:
>It might be helpful to add a comment to the docstring or info page
>for nreverse saying that its argument is modified such that
>afterwards it is a 1-element list containing the last element of the
>reversed list.

Why?  Then if someone came up with a way to do the reversing efficiently in
a different way, they wouldn't be able to change it, because the
documentation would lock them into the current behavior.

The documentation should only specify the parts of the behavior that users
can depend on, not incidental results of a particular implementation.

-- 
Barry Margolin, barry.margolin@level3.com
Level(3), Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-10-23 14:25                     ` Stefan Monnier
@ 2003-10-23 15:30                       ` Kevin Rodgers
  0 siblings, 0 replies; 27+ messages in thread
From: Kevin Rodgers @ 2003-10-23 15:30 UTC (permalink / raw)


Stefan Monnier wrote:
 >Roland Winkler wrote:

>>It might be helpful to add a comment to the docstring or info page
>>for nreverse saying that its argument is modified such that
>>afterwards it is a 1-element list containing the last element of the
>>reversed list.
> 
> I don't think this particular aspect of the behavior should be documented.
> Maybe we should add a note saying "the argument should not be used
> afterwards", but even that would not be very convincing.
> I think the only reasonable thing to put is a "don't use this unless you
> know what you're doing".

Why not document all the destructive list operations like delq, whose
doc string says:

If the first member of LIST is ELT, there is no way to remove it by side
effect; therefore, write `(setq foo (delq element foo))' to be sure of
changing the value of `foo'.

For nreverse, it would be:

Because the first cons cell of LIST is the last cons cell of the
returned list, write `(setq foo (nreverse foo))' to set `foo' to its
reversed value.

-- 
Kevin Rodgers

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-10-23 15:18                     ` Barry Margolin
@ 2003-10-23 22:03                       ` Roland Winkler
  2003-10-23 22:20                         ` Barry Margolin
  0 siblings, 1 reply; 27+ messages in thread
From: Roland Winkler @ 2003-10-23 22:03 UTC (permalink / raw)


Barry Margolin <barry.margolin@level3.com> writes:

> In article <m3u160cea8.fsf@tfkp07.physik.uni-erlangen.de>,
> Roland Winkler  <Roland.Winkler@physik.uni-erlangen.de> wrote:
> >It might be helpful to add a comment to the docstring or info page
> >for nreverse saying that its argument is modified such that
> >afterwards it is a 1-element list containing the last element of the
> >reversed list.
> 
> Why?  Then if someone came up with a way to do the reversing efficiently in
> a different way, they wouldn't be able to change it, because the
> documentation would lock them into the current behavior.
> 
> The documentation should only specify the parts of the behavior that users
> can depend on, not incidental results of a particular implementation.

The info page for nreverse gives an example for the results obtained
by the present implementation of nreverse where the argument is
converted into a 1-element list containing the last element of the
reversed list. I find this example rather confusing because it is
given wihtout further explanation which rules nreverse is obeying
when it modifies its argument destructively. However, if I
understand you correctly it does not even make sense to ask which
rules nreverse is using here because they depend on the
implementation of nreverse. It is nothing one could rely upon.

If indeed we are talking here about something that is
implementation-dependent, it would be better to replace this example
with a sentence saying that nreverse "destroys" its argument in an
implementation-dependent way such that only the return value is a
well-defined object. Then I would know that it doesn't make sense to
ask the question whether the argument of nreverse may be used for
anything else after it was passed to nreverse.

Or am I missing something here?

Roland

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-10-23 22:03                       ` Roland Winkler
@ 2003-10-23 22:20                         ` Barry Margolin
  2003-10-24 12:02                           ` Roland Winkler
  0 siblings, 1 reply; 27+ messages in thread
From: Barry Margolin @ 2003-10-23 22:20 UTC (permalink / raw)


In article <m33cdj8vdf.fsf@tfkp07.physik.uni-erlangen.de>,
Roland Winkler  <Roland.Winkler@physik.uni-erlangen.de> wrote:
>The info page for nreverse gives an example for the results obtained
>by the present implementation of nreverse where the argument is
>converted into a 1-element list containing the last element of the
>reversed list. I find this example rather confusing because it is
>given wihtout further explanation which rules nreverse is obeying
>when it modifies its argument destructively. However, if I
>understand you correctly it does not even make sense to ask which
>rules nreverse is using here because they depend on the
>implementation of nreverse. It is nothing one could rely upon.
>
>If indeed we are talking here about something that is
>implementation-dependent, it would be better to replace this example
>with a sentence saying that nreverse "destroys" its argument in an
>implementation-dependent way such that only the return value is a
>well-defined object. Then I would know that it doesn't make sense to
>ask the question whether the argument of nreverse may be used for
>anything else after it was passed to nreverse.
>
>Or am I missing something here?

The idea of Emacs documentation describing something as
"implementation-dependent" is kind of weird.  Emacs Lisp is not a general
purpose language with multiple implementations, it's a part of Emacs.  So
the documentation is describing just this one implementation.

I don't have the Emacs Lisp info pages online, but the built-in
documentation says:

   Reverse LIST by modifying cdr pointers.
   Returns the beginning of the reversed list.

This is terse, but it pretty much describes what I explained in detail a
few messages back.

The fact that any references to the old list will now refer specifically to
the last cons in the new list is a natural result of this; you just need to
understand how lists are built out of cons cells.  But this specific result
is not considered important -- no one ever writes a program that depends
specifically on what the old references point to.

The verbose documentation of all the destructive list operations should
mention that you must use the value to get the expected results all the
time, rather than depending on everything to work due to the lists being
modified in place.

-- 
Barry Margolin, barry.margolin@level3.com
Level(3), Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-10-23 22:20                         ` Barry Margolin
@ 2003-10-24 12:02                           ` Roland Winkler
  2003-10-24 15:06                             ` Barry Margolin
  2003-10-25 11:25                             ` Oliver Scholz
  0 siblings, 2 replies; 27+ messages in thread
From: Roland Winkler @ 2003-10-24 12:02 UTC (permalink / raw)


Barry Margolin <barry.margolin@level3.com> writes:

> The verbose documentation of all the destructive list operations should
> mention that you must use the value to get the expected results all the
> time, rather than depending on everything to work due to the lists being
> modified in place.

The first part of your sentence is exactly my point. Unlike the
docstring of nreverse, the info node presently does not say
explicitely that it is the _return_ value that should be used. (It
is hidden only implicitely in the sentence: "To avoid confusion, we
usually store the result of `nreverse' back in the same variable
which held the original list.")


The info node Rearrangement in the elisp manual says:

 - Function: nreverse list
     This function reverses the order of the elements of LIST.  Unlike
     `reverse', `nreverse' alters its argument by reversing the CDRs in
     the cons cells forming the list.  The cons cell that used to be
     the last one in LIST becomes the first cons cell of the value.

     For example:

          (setq x '(a b c))
               => (a b c)
          x
               => (a b c)
          (nreverse x)
               => (c b a)
          ;; The cons cell that was first is now last.
          x
               => (a)

The last two lines I find confusing because they use the argument of
nreverse after it was passed to nreverse. (They gave rise to my
question whether the argument of nreverse could be used for anything
"useful" after it was passed to nreverse.) Instead, the info node
could use the same sentence that is used in the docstring of nreverse:

    Returns the beginning of the reversed list.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-10-24 12:02                           ` Roland Winkler
@ 2003-10-24 15:06                             ` Barry Margolin
  2003-10-25 11:25                             ` Oliver Scholz
  1 sibling, 0 replies; 27+ messages in thread
From: Barry Margolin @ 2003-10-24 15:06 UTC (permalink / raw)


In article <m3ptgmdet4.fsf@tfkp07.physik.uni-erlangen.de>,
Roland Winkler  <Roland.Winkler@physik.uni-erlangen.de> wrote:
>The info node Rearrangement in the elisp manual says:
>
> - Function: nreverse list
>     This function reverses the order of the elements of LIST.  Unlike
>     `reverse', `nreverse' alters its argument by reversing the CDRs in
>     the cons cells forming the list.  The cons cell that used to be
>     the last one in LIST becomes the first cons cell of the value.
>
>     For example:
>
>          (setq x '(a b c))
>               => (a b c)
>          x
>               => (a b c)
>          (nreverse x)
>               => (c b a)
>          ;; The cons cell that was first is now last.
>          x
>               => (a)
>
>The last two lines I find confusing because they use the argument of
>nreverse after it was passed to nreverse. (They gave rise to my

Just to illustrate the danger of continuing to use it without re-assigning
it.  Typically you would write:

(setq x (nreverse x))

if you intended to keep using that variable.

>question whether the argument of nreverse could be used for anything
>"useful" after it was passed to nreverse.) Instead, the info node
>could use the same sentence that is used in the docstring of nreverse:
>
>    Returns the beginning of the reversed list.

What a function returns is called its "value".  So isn't this what is
described in the last sentence of the description?

-- 
Barry Margolin, barry.margolin@level3.com
Level(3), Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: replacing a certain element in a list with another
  2003-10-24 12:02                           ` Roland Winkler
  2003-10-24 15:06                             ` Barry Margolin
@ 2003-10-25 11:25                             ` Oliver Scholz
  1 sibling, 0 replies; 27+ messages in thread
From: Oliver Scholz @ 2003-10-25 11:25 UTC (permalink / raw)


Roland Winkler <Roland.Winkler@physik.uni-erlangen.de> writes:

> Barry Margolin <barry.margolin@level3.com> writes:
>
>> The verbose documentation of all the destructive list operations should
>> mention that you must use the value to get the expected results all the
>> time, rather than depending on everything to work due to the lists being
>> modified in place.
>
> The first part of your sentence is exactly my point. Unlike the
> docstring of nreverse, the info node presently does not say
> explicitely that it is the _return_ value that should be used. 

I agree that this could be more verbose. It is not, however,
undocumented as you seem to imply. I want to note---by the way---that
in my esteem destructive operations ship with a big sign on them:
“Dangerous! Handle with caution!”

> (It is hidden only implicitely in the sentence: "To avoid confusion,
> we usually store the result of `nreverse' back in the same variable
> which held the original list.")

I think that sentence is meant to say “... back in the same variable
which held the original list rather than in *another*
variable. Because that original variable may still be around and you
could become heavily confused when you try to debug your program and
wonder why on earth your variable has such a very weird unexpected
value at some point. On the other hand that's what you get for
careless use of destructive functions ...”

[...]
> The last two lines I find confusing because they use the argument of
> nreverse after it was passed to nreverse.
[...]

Confusion is always bad. I think you are right, that this should be
more verbose. Please send a bug report: (info "(elisp)Caveats").

    Oliver
-- 
4 Brumaire an 212 de la Révolution
Liberté, Egalité, Fraternité!

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2003-10-25 11:25 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-09-30  8:38 replacing a certain element in a list with another Klaus Berndl
2003-09-30  9:05 ` David Kastrup
2003-09-30  9:59   ` Klaus Berndl
2003-09-30 10:03     ` David Kastrup
2003-09-30 10:19       ` Klaus Berndl
2003-09-30 12:12     ` Pascal Bourguignon
2003-09-30 14:14       ` Stefan Monnier
2003-09-30 14:26         ` Klaus Berndl
2003-09-30 14:16 ` Stefan Monnier
2003-09-30 14:28   ` Klaus Berndl
2003-09-30 15:03     ` Stefan Monnier
2003-09-30 15:30       ` Kevin Rodgers
2003-09-30 15:47         ` Stefan Monnier
2003-09-30 18:27           ` Roland Winkler
2003-09-30 20:01             ` Barry Margolin
2003-10-16 20:52             ` Kai Grossjohann
2003-10-22 20:06               ` Roland Winkler
2003-10-22 20:32                 ` Barry Margolin
2003-10-23 12:46                   ` Roland Winkler
2003-10-23 14:25                     ` Stefan Monnier
2003-10-23 15:30                       ` Kevin Rodgers
2003-10-23 15:18                     ` Barry Margolin
2003-10-23 22:03                       ` Roland Winkler
2003-10-23 22:20                         ` Barry Margolin
2003-10-24 12:02                           ` Roland Winkler
2003-10-24 15:06                             ` Barry Margolin
2003-10-25 11:25                             ` Oliver Scholz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).