help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Problem advising nreverse.


From: Pascal J. Bourguignon
Subject: Re: Problem advising nreverse.
Date: Sat, 12 Dec 2009 13:18:55 +0100
User-agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/22.3 (darwin)

Sergei Organov <osv@javad.com> writes:

> Hello,
>
> It seems that an advice set for `nreverse' function fails to be called
> when `nreverse' is called from a byte compiled function:
>
> (let ((calls))
>   (defun test (problem)
>     (setq calls (concat calls "["))
>     (defun foo () (nreverse '()))
>     (and problem (byte-compile 'foo))
>     (defadvice nreverse (before nrev-adv activate)
>       (setq calls (concat calls "nrev-adv")))
>     (foo)
>     (ad-unadvise 'nreverse)
>     (setq calls (concat calls "]")))
>   (test t) (test nil) (test t)
>   calls)
>
> Evaluating this gives me (in either GNU Emacs 22.2.1 or GNU Emacs 23.1.1):
>
> "[][nrev-adv][]"
>
> Is it bug or feature? What's going on here? 

Indeed, it is a feature.

Advices are not available from several call points:

1- when the advised function is called from C code.

2- when the advised function is a an opcode of the virtual machine.
   You can observe the difference between the two primitives nreverse
   and buffer-name for example, with:     

     (disassemble (byte-compile (lambda (x) (nreverse x))))
   vs.:
     (disassemble (byte-compile (lambda (x) (buffer-name x))))

   In the former case, nreverse is a byte code, and therefore no
   advice applies.  In the later case, buffer-name is called with the
   call byte code, which will go thru the advice.

Notice that if you really want to advice such a low level primitive
function as nreverse, you can replace it with a lisp function (and
recompile all the code that uses it).

   (defvar primitive-nreverse (symbol-function 'nreverse))
   (defun nreverse (list) (funcall primitive-nreverse list))

Then nreverse will be a normal lisp function and you will be able to
advise it.  Be sure to recompile all the code that uses nreverse
otherwise it will still shortcut to the primitive nreverse.

-- 
__Pascal Bourguignon__


reply via email to

[Prev in Thread] Current Thread [Next in Thread]