1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-01 08:17:38 +00:00

Update doc for advice changes.

* doc/lispref/advice.texi (Advising Functions, Defining Advice):
Special forms can no longer be advised.

* lisp/emacs-lisp/advice.el: Update commentary.
This commit is contained in:
Chong Yidong 2013-12-26 11:27:45 +08:00
parent ed88fb10f4
commit 2200a8c91d
4 changed files with 48 additions and 63 deletions

View File

@ -1,3 +1,8 @@
2013-12-26 Chong Yidong <cyd@gnu.org>
* advice.texi (Advising Functions, Defining Advice): Special forms
can no longer be advised.
2013-12-25 Chong Yidong <cyd@gnu.org>
* keymaps.texi (Active Keymaps): Re-organize the text.

View File

@ -6,41 +6,43 @@
@chapter Advising Emacs Lisp Functions
@cindex advising functions
The @dfn{advice} feature lets you add to the existing definition of
a function, by @dfn{advising the function}. This is a cleaner method
for a library to customize functions defined within Emacs---cleaner
than redefining the whole function.
@cindex piece of advice
Each function can have multiple @dfn{pieces of advice}, each of
which can be separately defined and then @dfn{enabled} or
@dfn{disabled}. All the enabled pieces of advice for any given
function actually take effect when you @dfn{activate advice} for that
function, or when you define or redefine the function. Note that
enabling a piece of advice and activating advice for a function are
not the same thing.
The @dfn{advice} feature lets you add to the existing definition of
a function, by @dfn{advising the function}. A function can have
multiple @dfn{pieces of advice}, each of which can be separately
defined, and separately enabled or disabled (@pxref{Activation of
Advice}). Each piece of advice can alter almost anything about the
function, including its argument list, what the function does when it
runs, and the value it returns.
Advice is useful for altering the behavior of existing calls to an
existing function. If you want the new behavior for new function
calls or new key bindings, you should define a new function or
command, and have it use the existing function as a subroutine.
Advice can be useful for altering the behavior of an existing
function without having to redefine the whole function. However, it
can be a source of bugs, since existing callers to the function may
assume the old behavior, and work incorrectly when the behavior is
changed by advice. Advice can also cause confusion in debugging, if
the person doing the debugging does not notice or remember that the
function has been modified by advice.
Advising a function can cause confusion in debugging, since people
who debug calls to the original function may not notice that it has
been modified with advice. Therefore, if you have the possibility to
change the code of that function to run a hook, please solve the
problem that way. Advice should be reserved for the cases where you
cannot get the function changed. In particular, Emacs's own source
files should not put advice on functions in Emacs. There are
currently a few exceptions to this convention, but we aim to correct
them.
For these reasons, advice should be reserved for the cases where you
cannot modify a function's behavior in any other way. If it is
possible to do the same thing via a hook, that is preferable
(@pxref{Hooks}). If you simply want to change what a particular key
does, it may be better to write a new command, and remap the old
command's key bindings to the new one (@pxref{Remapping Commands}).
In particular, Emacs's own source files should not put advice on
functions in Emacs. (There are currently a few exceptions to this
convention, but we aim to correct them.)
Unless you know what you are doing, do @emph{not} advise a primitive
(@pxref{What Is a Function}). Some primitives are used by the advice
mechanism; advising them could cause an infinite recursion. Also,
many primitives are called directly from C code. Calls to the
primitive from Lisp code will take note of the advice, but calls from
C code will ignore the advice.
Macros can also be advised, in much the same way as functions.
However, special forms (@pxref{Special Forms}) cannot be advised.
It is possible to advise a primitive (@pxref{What Is a Function}),
but one should typically @emph{not} do so, for two reasons. Firstly,
some primitives are used by the advice mechanism, and advising them
could cause an infinite recursion. Secondly, many primitives are
called directly from C, and such calls ignore advice; hence, one ends
up in a confusing situation where some calls (occurring from Lisp
code) obey the advice and other calls (from C code) do not.
@menu
* Simple Advice:: A simple example to explain the basics of advice.
@ -140,10 +142,9 @@ syntax of @code{defun} and @code{defmacro}, but adds more:
@end example
@noindent
Here, @var{function} is the name of the function (or macro or special
form) to be advised. From now on, we will write just ``function'' when
describing the entity being advised, but this always includes macros and
special forms.
Here, @var{function} is the name of the function (or macro) to be
advised. From now on, we will write just ``function'' when describing
the entity being advised, but this always includes macros.
In place of the argument list in an ordinary definition, an advice
definition calls for several different pieces of information.

View File

@ -901,9 +901,10 @@ value when looking up variables.
** `defadvice' does not honor the `freeze' flag and cannot advise
special-forms any more.
** `dolist' in lexical-binding mode does not bind VAR in RESULT any more.
VAR was bound to nil which was not tremendously useful and just lead to
spurious warnings about an unused var.
---
** `dolist' no longer binds VAR while evaluating the RESULT form,
when lexical binding is enabled. Previously, VAR was bound to nil,
which often led to spurious unused-variable warnings.
** The return value of `backup-buffer' has changed.
The second argument is no longer an SELinux context, instead it is an

View File

@ -295,8 +295,8 @@
;; {<after-K-1-body-form>}*
;; ad-return-value))
;; Macros and special forms will be redefined as macros, hence the optional
;; [macro] in the beginning of the definition.
;; Macros are redefined as macros, hence the optional [macro] in the
;; beginning of the definition.
;; <arglist> is either the argument list of the original function or the
;; first argument list defined in the list of before/around/after advices.
@ -698,6 +698,7 @@
;; problems because they get expanded at compile or load time, hence, they
;; might not have all the necessary runtime support and such advice cannot be
;; de/activated or changed as it is possible for functions.
;;
;; Special forms cannot be advised.
;;
;; MORAL: - Only advise macros when you are absolutely sure what you are doing.
@ -1563,29 +1564,6 @@
;; flexibility and effectiveness of the advice mechanism. Macros that were
;; compile-time expanded before the advice was activated will of course never
;; exhibit the advised behavior.
;;
;; @@ Advising special forms:
;; ==========================
;; Now for something that should be even more rare than advising macros:
;; Advising special forms. Because special forms are irregular in their
;; argument evaluation behavior (e.g., `setq' evaluates the second but not
;; the first argument) they have to be advised into macros. A dangerous
;; consequence of this is that the byte-compiler will not recognize them
;; as special forms anymore (well, in most cases) and use their expansion
;; rather than the proper byte-code. Also, because the original definition
;; of a special form cannot be `funcall'ed, `eval' has to be used instead
;; which is less efficient.
;;
;; MORAL: Do not advise special forms unless you are completely sure about
;; what you are doing (some of the forward advice behavior is
;; implemented via advice of the special forms `defun' and `defmacro').
;; As a safety measure one should always do `ad-deactivate-all' before
;; one byte-compiles a file to avoid any interference of advised
;; special forms.
;;
;; Apart from the safety concerns advising special forms is not any different
;; from advising plain functions or subrs.
;;; Code: