reddit / emacs

Why does order matter with save-excursion and save-restriction

Mmneck · 2022-10-17 15:40
I have the exact same question as here, [On using save-excursion and save-restriction together : emacs (reddit.com)](https://www.reddit.com/r/emacs/comments/q51k1y/on_using_saveexcursion_and_saverestriction/). An answer was given but I don't understand it at all. I also do not understand the hint to expand the macro. Emacs tells me these functions aren't even macros, but special forms. ​ I was told to repost because it was old.
ieure · 2022-10-17 16:03
I think your link is broken, as it doesn't go anywhere with an answer. The documentation for `save-restriction` says (emphasis mine): > Execute BODY, saving and restoring **current buffer’s** restrictions. And `save-excursion` says: > Save point, and **current buffer**; execute BODY; restore those things. As [the section of the manual explains](https://www.gnu.org/software/emacs/manual/html_node/eintr/save_002drestriction.html): > If you write them in reverse order, you may fail to record narrowing **in the buffer to which Emacs switches after calling save-excursion**. So if you have some code like: (with-current-buffer "*origin*" ; Starting in *origin* (save-restriction ; Saves the restriction of *origin* (save-excursion (with-current-buffer "*other*" ; Switch to *other* (widen))))) ; Alters the restriction of *other* In this case, `*other*`'s restrictions will be changed, because `save-restriction` operates on `(current-buffer)` at the time it's evaluated, not on all buffers globally, or on buffers switched to within its body. But if you write: (with-current-buffer "*origin*" ; Starting in *origin* (save-excursion (with-current-buffer "*other*" ; Switch to *other* (save-restriction ; Saves the restriction of *other* (widen))))) Then `*other*`'s restrictions aren't changed. > I also do not understand the hint to expand the macro. Emacs tells me these functions aren't even macros, but special forms. An Emacs special form is any function implemented in C which doesn't follow the normal evaluation rules. Perhaps at the time the answer was written, they were macros, and subsequently got reimplemented in C for performance reasons.
Mmneck · 2022-10-17 16:52
Thanks for the example. I was referring to the comment here [https://www.reddit.com/r/emacs/comments/q51k1y/comment/hg3qj8p/?utm\_source=share&utm\_medium=web2x&context=3](https://www.reddit.com/r/emacs/comments/q51k1y/comment/hg3qj8p/?utm_source=share&utm_medium=web2x&context=3), which suggested to expand the macro. ​ Your example makes sense, however, you switched buffers in between the two commands. The line in manual says "one right after the other, " and I don't understand how switching them would cause different behavior in that case.
ieure · 2022-10-17 17:03
> Your example makes sense, however, you switched buffers in between the two commands. The line in manual says "one right after the other, " and I don't understand how switching them would cause different behavior in that case. I agree, I'm not sure how it would cause issues if you have the two with no intervening buffer switch. I think the emacs-devel list probably would have better context on what the docs are trying to say.
MaximRegret · 2022-10-19 17:57
The manual entry on [save-restriction](https://www.gnu.org/software/emacs/manual/html_node/elisp/Narrowing.html#index-save_002drestriction) has a better explanation: >If you use both save-restriction and save-excursion together, save-excursion should come first (on the outside). Otherwise, the old point value would be restored with temporary narrowing still in effect. If the old point value were outside the limits of the temporary narrowing, this would fail to restore it accurately. If you did something like (widen) (goto-char (point-min)) (save-restriction (save-excursion (narrow-to-region (1- (point-max)) (point-max)))) then point would wrongly end up just before `(point-max)`: because `save-excursion` fails to reset point to the beginning, since the buffer is still narrowed. But if `save-excursion` was on the outside like it's supposed to be, the buffer would be widened by the time it tries to restore point.