From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Uday S Reddy Newsgroups: gmane.emacs.help Subject: Re: `save-excursion' defeated by `set-buffer' Date: Sun, 13 Mar 2011 12:46:00 +0000 Message-ID: <19836.48264.656000.373465@gargle.gargle.HOWL> References: <4D792D16.1080900@easy-emacs.de> <83y64ksoik.fsf@gnu.org> <87aah0j7lf.fsf@rapttech.com.au> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Trace: dough.gmane.org 1300066782 2186 80.91.229.12 (14 Mar 2011 01:39:42 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Mon, 14 Mar 2011 01:39:42 +0000 (UTC) Cc: help-gnu-emacs@gnu.org To: Tim X Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Mon Mar 14 02:39:38 2011 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Pywkx-0006wi-8q for geh-help-gnu-emacs@m.gmane.org; Mon, 14 Mar 2011 02:39:35 +0100 Original-Received: from localhost ([127.0.0.1]:34152 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Pywkw-0004U2-Pe for geh-help-gnu-emacs@m.gmane.org; Sun, 13 Mar 2011 21:39:34 -0400 Original-Received: from [140.186.70.92] (port=51326 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PykgX-0004Yk-Cl for help-gnu-emacs@gnu.org; Sun, 13 Mar 2011 08:46:14 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PykgT-0007Er-0t for help-gnu-emacs@gnu.org; Sun, 13 Mar 2011 08:46:13 -0400 Original-Received: from sun60.bham.ac.uk ([147.188.128.137]:34986) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PykgS-0007EF-R6 for help-gnu-emacs@gnu.org; Sun, 13 Mar 2011 08:46:08 -0400 Original-Received: from [147.188.128.127] (helo=bham.ac.uk) by sun60.bham.ac.uk with esmtp (Exim 4.72) (envelope-from ) id 1PykgO-00066r-Pa; Sun, 13 Mar 2011 12:46:04 +0000 Original-Received: from mx1.cs.bham.ac.uk ([147.188.192.53]) by bham.ac.uk with esmtp (Exim 4.72) (envelope-from ) id 1PykgO-0005sV-Fg; Sun, 13 Mar 2011 12:46:04 +0000 Original-Received: from preston.cs.bham.ac.uk ([147.188.193.17] helo=MARUTI.cs.bham.ac.uk) by mx1.cs.bham.ac.uk with esmtp (Exim 4.51) id 1PykgM-0004He-LY; Sun, 13 Mar 2011 12:46:02 +0000 Original-Newsgroups: gnu.emacs.help In-Reply-To: <87aah0j7lf.fsf@rapttech.com.au> X-Mailer: VM 8.1.93a under 23.2.94.1 (i386-mingw-nt5.1.2600) X-detected-operating-system: by eggs.gnu.org: Solaris 10 (beta) X-Received-From: 147.188.128.137 X-Mailman-Approved-At: Sun, 13 Mar 2011 21:37:10 -0400 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:80069 Archived-At: Tim X writes: > > Seems all what's neccessary to know about save-excursion already > > is expressed in it's docstring. > > > > Not sure thats true. I've seen a lot of elisp code that does the > save-excursion, set buffer pattern, which makes me think maybe the > documentation is inadequate. It seems that reason for the widespread use of the save-excursion/set-buffer pattern is actually quite simple. Before Emacs version 20.1, there was no other way to do it. save-current-buffer was only introduced in 20.1. So, there is a lot of old code that uses the old pattern. Now, there is also a lot of new code that uses the old pattern because people learn their patterns from the old code. > > If people don't want the buffer restored alongside with point and mark, they > > should not use this form. > > > > I think it is a little more subtle than that. People may be using it > under the expectation that point and mark will also be saved in the > buffer accessed by set-buffer. No, I don't actually think that. (I notice that Andreas has questioned this assumption too.) If at all people are doing it consciously, they do it because they think it is harmless. You want to preserve the current-buffer. But, if you also preserve the point and mark, it seems like harmless redundancy. So, what is the big deal? It takes quite a bit of insight into the code to understand that it is actually *harmful* redundancy. The unintentional uses of save-excursion cover up potential bugs inside the code which don't get noticed because of this redundant saving. So, my test is pure and simple. Convert all the save-excursion's that the compiler complains about to save-current-buffer. If your code continues to run perfectly, you are my hero. If your code falls over, then you should accept that your code is buggy and it is only able to stand up on the crutches of what you thought was "harmless redundancy". Then it is up to you whether you want to fix the code or continue to live with it. But there are many of us who won't touch such code with a tadpole because we regard it as buggy. > Except we know it is often used incorrectly. I think Uday's point is > very valid here. When writing code, part of the aim is to communicate > intentions to others who may need to maintain or update the code in the > future. As Uday pointed out, using save-excursion followed by set-buffer > muddies the intention and decreases clarity. Unfortunately, it is more than a question of clarity. It is a question of correctness. Let me restate my example from Friday a bit more explicitly (defun my-beautiful-function () (save-excursion (set-buffer B) (goto-char x) (setq a (find-something)) ...)) (defun find-something () (.... (set-buffer A) (goto-char y) ...)) find-something is *buggy* here. It is moving point in buffer A though it wasn't supposed to. However, my-beautiful-function works fine as long as I call it in buffer A because the "harmlessly redundant" save-excursion at its top-level restores A's point. Tomorrow, you decide to call my-beautiful-function from some other buffer C, and all hell breaks loose. You suddenly find that the point is moving in the unrelated buffer A and you have no idea why. So, rewrite the code as follows: (defun my-beautiful-function () (save-current-buffer (set-buffer B) (goto-char x) ... (setq a (find-something)) ...)) (defun find-something () (.... (save-current-buffer (set-buffer A) (save-excursion (goto-char y) ...))) Not only would you have mollified the compiler, but you will have much more robust code that will continue to function when used in unforeseen ways. Cheers, Uday