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: Uday Reddy
Subject: Re: `save-excursion' defeated by `set-buffer'
Date: Fri, 11 Mar 2011 23:06:30 +0000
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.15) Gecko/20110303 Thunderbird/3.1.9

On 3/11/2011 8:52 AM, Andreas Röhler wrote:

Maybe let's put the question another way:

is there an example, where save-excursion will fail, ie not restore the
buffer due to a set-buffer afterwards?

That is not the right question to ask, in my opinion. save-excursion will restore the buffer. But save-current-buffer, which I recommended right at the outset of this discussion, will also restore the buffer. So, you should be asking the question, "why am I using save-excursion instead of save-current-buffer?" After all, if you are changing buffers, then you want to restore the current-buffer in the end. You don't need to restore the point and mark.

Despite the obviousness of save-current-buffer/set-buffer pattern, there is a lot of code out there that uses the save-excursion/set-buffer pattern. Why that is, I don't know. But, here is the problem that can arise with this misused pattern. Suppose you are in buffer A and you run:

   (save-excursion
      (set-buffer B)
      (goto-char x)
       ..... lots of deep function calls, say
       (....
          (set-buffer A)
          (goto-char y)
        ...))))

Two problems here:

- B's point has moved to x. Is that supposed to be permanent? It is not clear. The save-excursion may seem to indicate that we want to preserve its point. But, it is only A's point that is being preserved. B's point is not.

- A's point is being moved to y deep inside the code. Is that supposed to be permanent? Again, it is not clear. That movement is being cancelled by the outer save-excursion. But if the intent is to restore A's point after the temporary movement to y, shouldn't the save-excursion be close to the (goto-char y) statement?

If tomorrow, you happen to run this code in buffer C, you will find that A's point is suddenly moving. (The outer save-excursion will restore C's point instead of A's point.) If your code is sufficiently complicated, it will probably take quite some digging to find the problem.

So the right programming style is to use

    (save-current-buffer
        (set-buffer B)
        ...)

or

    (save-excursion
        (goto-char y)
        ....)

But

   (save-excursion
        (set-buffer B)
        ...)

is neither here nor there.  Hence, the compiler warning.

Hope this helps.

Cheers,
Uday

PS: By the way, I maintain the mail reader VM, which has tons and tons of the bad save-excursion/set-buffer pattern. But changing those save-excursion's to save-current-buffer's is not easy. There could be unprotected point movements buried deep inside which happen to work coincidentally because they are buried under a stack of save-excursion forms. So, it is best to use the right programming style from the beginning to save unnecessary head aches down the road.




reply via email to

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