Open yurikhan opened 7 years ago
If your function is not specifically intended to modify global shared state, preserve it by wrapping your function body in the appropriate (save-) or (with-) macros.
For the match data, at least, that goes against the current advice on emacs-devel: any function A when calling function B should assume that B can modify the match data. And it should itself wrap the call to B in save-match-data
, if it needs it preserved. We could document when a function preserves the match data, however.
As far as moving point or changing buffers go, yes, I think those should be generally documented.
That’s actually okay, too.
As an analogy, processor/OS/compiler ABIs document certain registers as “must be preserved across calls” and certain other registers as “may be destroyed by any call”.
We could have a (n incomplete) list of parts of global state which should or need not be preserved.
Elisp has a lot of mutable global state. Some of it is highly shared. And it is very easy to modify global, highly shared state inadvertently. This includes point, mark, narrowing, match data, current buffer, selected window, selected frame, and who knows what else.
For example, calling
(looking-at "[ \t]")
to check if we are on whitespace clobbers match data. If this is done in a function, the caller has to wrap its invocation in a(save-match-data)
if match data is important.Proposal:
(save-*)
or(with-*)
macros.