[comp.emacs] possible s-expr management error

jthomas@NMSU.EDU (11/16/89)

Machine: Sun 3/60
OS: SunOS 3.5
Emacs: gnu emacs 18.51.28
Compiler: I'm not sure, I think gcc 1.34, but maybe just Sun cc
Gnus: gnus 3.12
Routine: gnus-reorder-newsrc-file of David Lawrence of 27 Jun 89

Situation:
I've finally tried to use the gnus-reorder-newsrc-file that David posted
last June.  But it dies with a "consp nil" error message in a call to
setcdr.  So I've looked at what's happening using the debugger.  It is
dying on the line:

              (insert "-")
----->>>>     (setcdr (nth 2 compress-group)
                      (cdr (nth (1- (length compress-group)) compress-group)))
              (setcdr (memq (nth 2 compress-group) compress-group) nil))))

, because compress-group is nil .  So I checked around to see why that
might be so.  To make a long story shorter, I wandered around and
reproducably get in:

        (if (or nosort (not reordered)) nil
          (sort-lines nil (progn (re-search-forward "! " nil t)
                                 (beginning-of-line) (point)) (point-max))
---->>>   (setq gnus-unsub-assoc (sort gnus-unsub-assoc 'gnus-assoc-lessp)))

that before this line, gnus-newsrc-assoc is what it should be, but
afterwards it has been changed.  It is approximately the right size but is
now sorted (as if somehow the last lines of the reorder function have
already been called).  This would not be noticable if Murphy were really
playing games, but gnus-unsub-assoc is missing a couple of unsubscribed
newgroups that were in the original gnus-newsrc-assoc.  They should be
there, but since they're not the setcdr dies later.

I realize this scenario is a bit hard to believe, but has anyone else seen
something like this?  I looks to me as if the pointers for the unsub and
newsrc lists have gotten too intermingled.  Or am I dreaming?

Jim Thomas

barmar@leander.think.com (Barry Margolin) (11/16/89)

In article <8911160201.AA04995@NMSU.Edu> UNIX-EMACS@VM.TCS.Tulane.EDU writes:
>---->>>   (setq gnus-unsub-assoc (sort gnus-unsub-assoc 'gnus-assoc-lessp)))
>
>that before this line, gnus-newsrc-assoc is what it should be, but
>afterwards it has been changed.  It is approximately the right size but is
>now sorted (as if somehow the last lines of the reorder function have
>already been called).  This would not be noticable if Murphy were really
>playing games, but gnus-unsub-assoc is missing a couple of unsubscribed
>newgroups that were in the original gnus-newsrc-assoc.  They should be
>there, but since they're not the setcdr dies later.
>
>I realize this scenario is a bit hard to believe, but has anyone else seen
>something like this?  I looks to me as if the pointers for the unsub and
>newsrc lists have gotten too intermingled.  Or am I dreaming?

SORT is a destructive operation; it actually reorders the original list by
rearranging the cdr chain.  Therefore, any other references to that list
or any tail of it will see the rearrangement.

The simplest solution to this problem is to make a copy of the list before
sorting it, to guarantee that the list being sorted is not shared with
anything else.  This can be done with:

(defun copy-list (list)
  (append list nil))

The above code should then be changed to

(setq gnus-unsub-assoc (sort (copy-list gnus-unsub-assoc) 'gnus-assoc-lessp))
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

tale@pawl.rpi.edu (David C Lawrence) (11/16/89)

In article <8911160201.AA04995@NMSU.Edu> jthomas@NMSU.EDU writes:
Jim> I realize this scenario is a bit hard to believe, but has anyone
Jim> else seen something like this?  I looks to me as if the pointers
Jim> for the unsub and newsrc lists have gotten too intermingled.  Or
Jim> am I dreaming?

I've not seen the problem at all with multiple invocations of the hook
daily since I wrote it; that does not mean, however, that there isn't
a problem.  Perhaps I am have just never done whatever it was that
triggered this for you.  If you could please send me more information
on the problem I would be happy (well, sorta ... :-) to work through
it with you.

In <31688@news.Think.COM> barmar@leander.think.com (Barry Margolin) writes:
Barry> SORT is a destructive operation; it actually reorders the
Barry> original list by rearranging the cdr chain.  [...]

Barry> The above code should then be changed to
Barry> (setq gnus-unsub-assoc (sort (copy-list gnus-unsub-assoc) 'gnus-assoc-lessp))

It should not.  That screws the function up.  I used sort because
sort was what I wanted.  I am well aware of the lisp functions which
directly alter list structure and the usage of both sort and setcdr in
the function was for exactly that behaviour.

Dave
-- 
 (setq mail '("tale@pawl.rpi.edu" "tale@ai.mit.edu" "tale@rpitsmts.bitnet"))

tale@pawl.rpi.edu (David C Lawrence) (11/18/89)

In <31688@news.Think.COM> barmar@leander.think.com (Barry Margolin) writes:
Barry> SORT is a destructive operation; it actually reorders the
Barry> original list by rearranging the cdr chain.  [...]

Barry> The above code should then be changed to
Barry> (setq gnus-unsub-assoc (sort (copy-list gnus-unsub-assoc) 'gnus-assoc-lessp))

In <1989Nov16.061626.22143@rpi.edu> tale@pawl.rpi.edu (Me):
Me> It should not.  That screws the function up.  I used sort because
Me> sort was what I wanted.  I am well aware of the lisp functions which
Me> directly alter list structure and the usage of both sort and setcdr in
Me> the function was for exactly that behaviour.

Boy, do I love the taste of shoe leather.

The nifty little sorting hack which worked for me because I had a
mostly sorted list anyway ended up being a krufty mismanagement of
pointers which is unnecessary because the function cleans up after
itself later anyway.  Blargh.

As Barry suggests, but using an Emacs builtin:

  (setq gnus-unsub-assoc
        (sort (copy-sequence gnus-unsub-assoc) 'gnus-assoc-lessp))

is the appropriate thing to do.

Sheepishly,
Dave
-- 
 (setq mail '("tale@pawl.rpi.edu" "tale@ai.mit.edu" "tale@rpitsmts.bitnet"))

tale@rpi.UUCP (David C Lawrence) (11/18/89)

In <31688@news.Think.COM> barmar@leander.think.com (Barry Margolin) writes:
Barry> SORT is a destructive operation; it actually reorders the
Barry> original list by rearranging the cdr chain.  [...]

Barry> The above code should then be changed to
Barry> (setq gnus-unsub-assoc (sort (copy-list gnus-unsub-assoc)
 'gnus-assoc-lessp))

In <1989Nov16.061626.22143@rpi.edu> tale@pawl.rpi.edu (Me):
Me> It should not.  That screws the function up.  I used sort because
Me> sort was what I wanted.  I am well aware of the lisp functions which
Me> directly alter list structure and the usage of both sort and setcdr in
Me> the function was for exactly that behaviour.

Boy, do I love the taste of shoe leather.

The nifty little sorting hack which worked for me because I had a
mostly sorted list anyway ended up being a krufty mismanagement of
pointers which is unnecessary because the function cleans up after
itself later anyway.  Blargh.

As Barry suggests, but using an Emacs builtin:

  (setq gnus-unsub-assoc
        (sort (copy-sequence gnus-unsub-assoc) 'gnus-assoc-lessp))

is the appropriate thing to do.

Sheepishly,
Dave
--
 (setq mail '("tale@pawl.rpi.edu" "tale@ai.mit.edu" "tale@rpitsmts.bitnet"))