53

Emacs 24.4 comes with a new advice system. The NEWS file says:

** New package nadvice.el offers lighter-weight advice facilities. It is layered as:

*** add-function/remove-function, which can be used to add/remove code on any function-carrying place, such as process filters or <foo>-function hooks.

*** advice-add/advice-remove to add/remove a piece of advice on a named function, much like defadvice does.

Q: What are the practical benefits and implications of this new package?

I am especially interested in answers addressing the following points:

  • If I am only using advice to customize Emacs (as opposed to writing add-on packages), do I need to switch to the new system? Will it replace the old system at some point?

  • What exactly can I do with the new system that I can't accomplish with defadvice?

  • What is the significance of being able to "add/remove code on any function-carrying place"?

57

The new advice system has the following advantages:

  • add-function: This is brand new functionality that simply was not part of defadvice. It is a kind of hybrid between add-hook and defadvice. In the future, expect more foo-function variables (modified via add-function) and less foo-functions (modified via add-hook). This functionality was the main motivation to implement the new advice system, triggered by a bug report asking how to "share" a process-filter between different packages.

  • Implementation simplicity: once add-function was implemented, it takes only 8KB to implement the advice-add functionality which brings pretty much all the functionality of the 100KB of advice.el.

  • Design simplicity: defadvice has various notions that are generally difficult to understand precisely and/or rarely used. E.g. the difference between "enabling" and "activating" advices. Or the meaning of "pre" and/or "compiled". There are also quirks in the handling of ad-do-it, such as the fact that it looks like a variable-reference rather than a call, or the fact that you need to (setq ad-return-value ...) explicitly rather than simply returning the value.

  • Defadvice suffers from various problems w.r.t macroexpansion and compilation: the body of an advice is not exposed as "code" (which the compiler and macroexpander see) but as "data" which is later on combined to make up an expression. So macroexpansion happens late (which can causes surprises if you use things like (eval-when-compile (require 'foo))) and lexical-scoping is hard to preserve correctly.

As for whether you need to switch to the new system: I do intend to get rid of the old defadvice at some point in the future, but I think this future is relatively distant (and it'll first have to move to lisp/obsolete, then later to GNU ELPA).

  • 1
    Do plans exist to add to nadvice.el the same argument-modification functionality offered by the old advice system? – Aaron Miller Jan 2 '16 at 17:13
  • No, that pretty much makes no sense in the context of nadvice.el where the advice functions are plain old normal functions. But you can use :around advice (or :filter-args or :filter-result advice) to get the same effect. – Stefan Jan 2 '16 at 18:15
  • 2
    I can't, though. Suppose I want to advise a function of two arguments, replacing only the second argument, so that the advised function will still prompt according to its interactive form for the first one. New advice seems to provide a couple of different ways to replace an advised function's interactive form, but I don't see anything offering more nuance than that. – Aaron Miller Jan 3 '16 at 11:41
  • @AaronMiller: Please make it a separate SX question, so it can be discussed without the artificial limits of SX comments. – Stefan Jan 3 '16 at 14:56
  • Done, at emacs.stackexchange.com/q/19233/2162. I appreciate your following up. (I'd also be curious to see the bug report you mention in your answer, but haven't been able to find it via Google or mailing list archive search. Do you mind linking it?) – Aaron Miller Jan 3 '16 at 19:21
9

One of the clear benefits of advice being normal functions is that you can visit a definition with find-function.

At present, when viewing the help for a (new-style) advised function, it provides a link to the help for the advice function, and from there a link to the source (as usual for function help).

The old system provided the advice docstring inline, but there was no way to see the code (I usually resorted to rgrep).

(Personally I'd like to see a blend of the old and new approaches to displaying the help, as I liked having the inline docstring, but I'm sure that's possible down the track.)

  • 2
    Yes, it is too bad that the new advice system does not let you add to the existing doc string like defadvice does. See this Emacs bug report. This is shortcoming. – Drew Nov 5 '14 at 4:59
8

From the file header:

;;; Commentary:

;; This package lets you add behavior (which we call "piece of advice") to
;; existing functions, like the old `advice.el' package, but with much fewer
;; bells and whistles.

As I read it, the primary goal is to be simpler than the old advice system, not to have more capabilities. Reading the docs, it seems that advice-add contains a subset of defadvice's functionality, while add-function contains some nice functionality for advising non-traditional functions such as process filters (which was probably possible with defadvice, but I'm not sure how).

As far as I know, defadvice is not officially deprecated so you should feel free to keep using it for now (and if you're a package author, you probably want to keep using it until 24.4 becomes more widely adopted). However, it sounds like the Emacs authors want to migrate completely to the new system eventually, so it probably makes sense to slowly switch over.

0

One thing I haven't seen mentioned here -- though in some ways it is due to the simpler approach (better modularity and "glue") of the "new" advice system, which has been mentioned in other answers -- is this: it is much easier to add, combine, remove, reorder, etc. nadvice advice.

It's even possible to do so interactively, dynamically, though nadvice needs a little help to facilitate this. I'm not aware of other use of nadvice this way (interactive composition of advice), but there is at least one such application. I make use of it in Isearch+, to let you add and remove combinations of arbitrary Isearch filter predicates (filters) while searching.

IOW, just as you change your search pattern incrementally, so you can refine your search on the fly using multiple filters.

Isearch filtering is done using variable isearch-filter-predicate, which has been available for quite a while now. Yet Isearch filters are not defined often. They are typically static and predefined for a given context (e.g. Wdired). It's not very easy for users to define and use them, interactively at least.

There is only one variable, isearch-filter-predicate, so changing filtering really means changing the single filter predicate, which amounts to composing functions, combining predicates, to narrow, expand, or otherwise modify the search.

But that's exactly what nadvice is good at. In sum, nadvice is so handy for combining functions that it can make it easy to interactively refine search filtering. (See Dynamic Isearch Filtering for more about this.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.