From 2200a8c91de23f9749d1b3c961c4f8bb3145ddfa Mon Sep 17 00:00:00 2001 From: Chong Yidong Date: Thu, 26 Dec 2013 11:27:45 +0800 Subject: [PATCH] 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. --- doc/lispref/ChangeLog | 5 +++ doc/lispref/advice.texi | 77 ++++++++++++++++++++------------------- etc/NEWS | 7 ++-- lisp/emacs-lisp/advice.el | 28 ++------------ 4 files changed, 51 insertions(+), 66 deletions(-) diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 354efd5f40c..2956b907d77 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,8 @@ +2013-12-26 Chong Yidong + + * advice.texi (Advising Functions, Defining Advice): Special forms + can no longer be advised. + 2013-12-25 Chong Yidong * keymaps.texi (Active Keymaps): Re-organize the text. diff --git a/doc/lispref/advice.texi b/doc/lispref/advice.texi index e8d1bd3cdbc..122f1805c1e 100644 --- a/doc/lispref/advice.texi +++ b/doc/lispref/advice.texi @@ -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. - - 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. - - 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. - - 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. + 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 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. + + 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.) + + 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. diff --git a/etc/NEWS b/etc/NEWS index de461aa2bf7..5aedab61c20 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -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 diff --git a/lisp/emacs-lisp/advice.el b/lisp/emacs-lisp/advice.el index 7996f9a2263..f2d5ce9a11e 100644 --- a/lisp/emacs-lisp/advice.el +++ b/lisp/emacs-lisp/advice.el @@ -295,8 +295,8 @@ ;; {}* ;; 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. ;; 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: -- 2.39.2