help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: `save-excursion' defeated by `set-buffer'


From: Drew Adams
Subject: RE: `save-excursion' defeated by `set-buffer'
Date: Mon, 14 Mar 2011 01:43:51 -0700

> > No way of knowing what most people felt or feel, and it
> > doesn't matter because polls are not taken anymore when
> > deciding...  (Poor Emacs.)
> 
> No, polls are not in.  It was pointed out that the Gnu 
> project is not a democracy.  It is an enlightened dictatorship
> in the Socratic style.  I am a great fan of Socrates myself and
> I wouldn't want the Gnu project to go down the tube like the
> Athenian democracy did.

Tell it to Enlightened Dictator RMS.  He's the one who's most often calling for
Emacs Dev to poll the users these days, as had been done sometimes during His
reign.  Maybe you should explain to him that listening to him about polling
would send the GNU project down the tube.

> > Wrt the supposed danger, David K replied this to Stefan 
> > (who replied to me, defining the danger)
> > http://lists.gnu.org/archive/html/emacs-devel/2010-01/msg00588.html:
> >
> >>>> just what is inherently wrong or dangerous (meriting a
> >>>> warning) with code like the following, to do some work 
> >>>> in other buffers yet return to the original buffer AND
> >>>> restore its point and mark?
> >>>>
> >>>> (save-excursion
> >>>>    (set-buffer FOO)
> >>>>    ; Pick up some info in FOO,&  perhaps assign it to a var
> >>>>    (set-buffer BAR)
> >>>>    ; Calculate something in BAR,&  perhaps record it too
> >>>>    ...
> >>>> )
> >>>
> >>> What is dangerous about it is that dependong on which 
> >>> buffer is current before executing this code, the point-saving
> >>> will either do something or nothing.
> >>
> >> Wrong.  It will always restore the _original_ buffer and 
> >> its point on exit of the save-excursion form.
> 
> I don't see anything "wrong" in Stefan's point.  Whether the 
> code has a side effect or not depends on which buffer it is
> running in. It has a side effect on any buffer except the
> current buffer.  That is strange and buggy code.  Stefan's
> point stands.

What side effect are you talking about?  Picking up info and assigning it to a
var?  That happens regardless of which buffer was originally current.  Restoring
point?  That happens on _no_ buffer except the originally current one.  And it
happens there regardless of which buffer that was (even if it was FOO or BAR).

There is nothing strange or buggy about that code.  `save-excursion' here, as
always, does just what David said: it makes the original buffer current again
and restores its point and mark.

More to the point, there is certainly nothing DANGEROUS here, which is what
Stefan claimed.  This was supposedly his _definition_ of the DANGER involved
with using `save-excursion' with `set-buffer' - the reason for issuing a
WARNING.  "What is dangerous about it is..." - but no danger was indicated.

> I am not sure what David's point is. actually.  "It will 
> always restore the original buffer and its point."

That's the point.  The behavior of `save-excursion' does not depend on which
buffer was originally current.  It does not do something different if FOO was
current or TOTO was.  It _always_ restores the original buffer and its point,
whatever that buffer might have been.

Stefan claims that it is "dangerous" that "the point-saving" is a no-op for any
buffer other than the originally current one.  And that's the exact job
`save-excursion' has; it's exactly what it is designed to do.  Claiming that is
tantamount to claiming that `save-excursion' is dangerous whenever you make
another buffer current somewhere in its body.

> But, what is so special about the original buffer?  Is it fine
> for the code to muck up every buffer other than the original buffer?

What on earth are you talking about?  What is being mucked up?

The _point_ of `save-excursion' is to restore the original buffer and its point
(and mark) - nothing more.  It has never had as object to do the same for any
other buffers.  The doc is very clear about what it does.  Stefan might think
that some people get fooled into thinking that it saves and restores other
buffers and their points, but he's shown no evidence for that.  And no evidence
of any "danger".

> > David is correct of course.  And Stefan's explanation of the "danger"
> > does not indicate any danger, in any case.  Where's the beef?
> 
> I haven't seen Stefan use words like "danger".

You haven't?  Look above.  "What is dangerous about it is..."  He is answering
the direct question of what's so dangerous.

> I probably overstated my wariness in my previous message.  Code that 
> generates the "suspicious" warnings is not necessarily dysfunctional. 
> It is just fragile.  It can break when modified or extended.  
> But what I would be really wary of developers that fail to understand 
> the issue and blame it all on the compiler stupidity instead.

Failing to understand `save-excursion' is what this is all about, AFAICT.  There
is no reason to expect it to save and restore anything to do with any buffer
other than the original one.  The doc is very clear about what it does.  It is
not a bug that `save-excurstion' does not prevent you from "mucking up" anything
you might want to.  That's not its job.

> > More seriously, RMS et al who created `save-excursion' were 
> > not idiots.  They explicitly designed it to save and restore
> > which buffer is current, in addition to its point and mark.
> > Why, do you suppose?
> 
> They designed them in the early days and those were good first-cut 
> solutions.

A first-cut that is several decades old now.  Tried and true, I'd say.  Why do
you suppose they had it save and restore point and mark?  What were they
thinking?

There is always room for improvement to Emacs, of course.  But no problem with
`save-excursion' has yet been pointed out - beyond a claim that some users might
somehow expect it to save and restore additional buffers.

> But we learn from experience and make progress.  Now, 
> `save-current-buffer' represents one half of `save-excursion',
> and it is exactly the half that is relevant to `set-buffer'.  So,
> when the elisp gurus recommend that you use that instead of
> `save-excursion', why is there this resistance?  Why these endless
> debates?

First, no one has disagreed that `save-current-buffer' and `with-current-buffer'
are appropriate when you only want to save which buffer is current, and not its
point.

Second, "the elisp gurus" are not lined up as a group behind this warning, even
if it has been accepted as a fait accompli.  And you saw in this very thread
recently that two such gurus (Eli, David K) have _very_ different understandings
of what the warning is even trying to convey.

Third, the debate about the warning ended in emacs-devel months ago (a year
ago).  Users are now coming in contact with the incomprehensible warning for the
first time and have therefore raised the question (WTF?) in help-gnu-emacs.

_You_ then brought it back to emacs-devel by proposing a change to the manual
that distorts things (IMHO), removing `save-excursion' from the passages that
discussed its use.  Yes, I know that you were honestly trying to help explain
the message, but you can see how that has caused a new discussion of what the
warning means (what "problems" or "dangers" it tries to avoid).

It is unlikely that the confusion introduced by this warning message will go
away soon, as users discover it anew.  Get the gurus to agree about what the
message really means - what the problem to be avoided is, and then maybe you can
add the result to the manual to clear up the message in a way that won't stir
the pot.  And perhaps at the same time improve the message based on agreement of
what it means.

> > And most users of it over the years have used it well - 
> > without any warnings.  If you automatically think that such a
> > warning indicates bad code or inadequate knowledge of Emacs Lisp
> > then you are jumping to a wild, indiscriminate conclusion, IMO.
> 
> They haven't used it well.

And the proof is?

> It is really not possible to use it correctly.

Well, here you and Stefan apparently disagree.  And you seem to disagree with
yourself as well, as you indicated that only a small minority of the occurrences
of `save-excursion' plus `set-buffer' in your VM code needed to be fixed.
(Stefan said the same of the Emacs sources; they have already been fixed, IIUC.)

> Slapping a save-excursion at the top level hides all the 
> side effects and you don't know what unwanted side effects 
> have occurred inside the code.

No idea what you're referring to.

> As you know, I maintain VM which was developed by a star programmer
> like Kyle Jones.  But if I replace its save-excursion's 
> by save-current-buffer's, it falls down pretty badly, with the buffer 
> points moving in all kinds of unpredictable ways.

Not surprising.  `save-current-buffer' is not `save-excursion'.

> For all I know, there might be only one or two unprotected
> point movements in there.  But they are enough to wreak havoc.

Were they wreaking havoc before you replaced `save-excursion' willy-nilly with
`save-current-buffer'?

> Tracking them down is incredibly hard.  The best I can do is to
> replace a few save-excursions at a time and watch carefully to see
> if anything goes wrong.  It will take me a long time to get rid of
> all the save-excursions.

And you are trying to get rid of all the `save-excursion's why?  Did someone
scare you into thinking that `save-excursion' is evil?  Stefan disagrees, FWIW.
 
> So, my best advice would be, don't do it.  Don't use save-excursion
> with set-buffer.

My advice would be _not_ to try willy-nilly getting rid of `save-excursion'.
It's probably there in your code for a reason.  If you are sure you understand
each use and you know that a given use can be changed to `save-current-buffer'
or `with-current-buffer' with no loss, then go for it.  But it doesn't sound
like you are too sure of that.

> It is completely illogical.  There is no need for it.  The 
> compiler is right.  Please pay attention.

Sheesh.  Give us a break.  Please pay attention yourself.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]