emacs-devel
[Top][All Lists]
Advanced

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

Re: save-excursion again


From: Stephen J. Turnbull
Subject: Re: save-excursion again
Date: Sat, 19 Jun 2010 23:50:05 +0900

Uday S Reddy writes:

 > When I first got involved with VM, there were a host of problems that
 > were called "jumping cursor" issues.  You do something and the cursor
 > ends up at a different place.

The point is that if

    ;; current buffer is "bar"
    (save-excursion
     (set-buffer "foo")
     (frob-current-buffer))

protects "bar" from jumping cursor, then `frob-current-buffer' must
switch back to "bar" and move the cursor at some point.

If your code is doing that kind of thing, then you end up with

 > In fact, I would have rather liked a compiler that asked, do you
 > really want to do set-buffer without a save-excursion first?

But that's *not good enough*.  Suppose a new feature requires this
code:

    ;; current buffer is "bar"
    (frob-current-buffer)

Now you're going to see jumping cursor without a set-buffer to warn
you.  The obvious try is

    ;; current buffer is "bar"
    (save-excursion (frob-current-buffer))

but since `frob-current-buffer' is used in situations where jumping
cursor is bad, why not

(fset 'frob-current-buffer-internal (symbol-function 'frob-current-buffer))
(defun frob-current-buffer (&rest args)
  (save-excursion (apply #'frob-current-buffer-internal args)))

and save yourself future aggravation by using `frob-current-buffer'
except when point motion is the intent?

 > That is, set-buffer without save-excursion is dangerous, because it
 > might lead to the "jumping cursor" problem.

No.  It's the code *after* the set-buffer that's dangerous, not the
set-buffer.  That fact that you consider set-buffer per se dangerous
is a strong suggestion that your program is rotten with code that does
set-buffer and then moves point without a save-excursion.

 > I will assume you are joking.  But, why bother with any of this at
 > all?  What is wrong with the original code in the first place? 

Nothing, assuming that the whole project is already using functions
that have nasty side-effects of moving point in buffers they aren't
called from.  In that case it might be cheaper for you to wrap every
set-buffer and following code in a save-excursion, but it's not 100%
reliable.  And it's *much* better to write new code to avoid side
effects except in functions designed to produce side effects.

It's true that using the set-buffer heuristic you'll probably catch
*most* such issues, because a lot of the functions of the form

(defun find-something (quux)
  (set-buffer "bar")
  ;; I should have put a save-excursion *here* but didn't.  Oops.
  (if (search-forward quux nil t)
      (extract-info-from-line-in-bar)
    (error "No quux here, boss!")))

are mostly called from other buffers (in a context like VM, if you're
in "bar", you're probably already on the appropriate line, so you call
`extract-info-from-line-in-bar' directly, not via `find-something').

But you can't guarantee that.




reply via email to

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