Arguments: fspec class name position &rest forms
Starting in Allegro CL release 6.0, the new fwrapper facility, described in fwrappers-and-advice.htm, replaces the advice facility, and continued use of the advice facility is deprecated.
None of the arguments are evaluated. This macro advises the function fspec appropriately with code defined by the forms.
fspec specifies the function (or macro) to advise. This argument is normally a symbol but it can be any function name (see implementation.htm). See fwrappers-and-advice.htm for information on advising macros. The information in the remainder of this definition relates to functions only.
class specifies the type of advice. The three
choices are :before
, :around
, and
:after
. :before
advice will be evaluated
before the advised function is called; :around
advice
will be evaluated around the calling of the advised function (in the
sense that the call to the function will be embedded within the
:around
code); :after
advice will be
evaluated after the advised function has been called. See below for
more information on classes of advice.
name specifies the name of the advice. Its
value may be nil
, but it is convenient to refer to advice by
name. Note that there can be only one piece of advice of each class
with a given name. (But there may be as many as you like without a
name, i.e. with nil
as the specified name.) If more advice is defined
with the same name and class as existing advice, the new advice will
replace the existing advice, thus taking its place.
position specifies the location of advice relative to other advice of the same class on the same function. The important point about this argument is that it is used only when the advice is first defined and is then forgotten. Therefore, the position is calculated with respect to already existing advice of the same class, whose positions are 0, 1, 2... regardless of the value of the position argument when they were defined. See fwrappers-and-advice.htm for examples that further explain this point.
There can be many pieces of advice of each class on a
function. position specifies where the piece of
advice currently being defined will go. position
may be a non-negative integer, a name or nil
. If it is a number, then the lower the number,
the farther the advice will be from the actual evaluation of the forms
defining the function itself. Thus for :before
and
:around
advice, advice 0 will be run first, then 1, 2, 3,
and so on, while for :after
advice, advice 0 will be run
last, preceded by 1, 2, 3, and so on. Say there are n pieces of advice
of the class of the advice being defined. The existing advice is
numbered 0, 1, 2, ..., n-
1, inclusive. Then a position of
0 will result in the new advice being placed farther from the function
call than all the rest of the advice, a position of k
where k
is between 1 and n-1
will be placed
farther then the k
th piece of existing advice, and a
position n
or larger will be placed nearest the function
call.
If position is nil
, the advice is put farther
from the function call then all currently-defined advice of the same
class. If position is a name of existing advice, the advice will be
placed next farther from the function call (before for
:before
and :around
, after for
:after
) than the named advice. Note that if new advice
has the same name and class as existing advice, it will replace the
existing advice and take the position of the existing advice. In that
case, the position argument will be ignored.
forms are the actual forms that will be
evaluated. All advice on a function is combined in an enclosing
cl:prog, so a return placed anywhere in any type of advice will
cause the advised function to return with the values specified with
the return, without any further advice code being evaluated and (if it
has not already done so) without the advised function being
evaluated. Syntactically, :around
advice should be
a single form. If multiple forms are specified, however, they are
automatically wrapped in a cl:progn. Warning:
forms cannot be the single form nil
. If you want the single form nil
(in, for example, :around advice to not call the
function and return nil
), specify
(progn nil)
instead.
:before
advice will be evaluated before the function
call. The argument list with which the function was called is
available to :before
advice. The argument list is stored
as the value of the variable excl:arglist
(this symbol
also names a function which returns the arguments list of an
operator). You may check the values in this list, change the values or
replace the list altogether with a new list. (If you replace the list,
be careful that it have the correct format for the function -- number
and types of arguments in the list -- or you may get an error, or
worse, a wrong result but no error.) :before
advice is
used only for its side effects. Any value returned by
:before
advice code is ignored.
:around
advice places the function call inside the
code of the advice. The keyword :do-it
signals where the
function should be called within the advice code. When Lisp encounters
the :do-it
, it calls the next piece of
:around
advice, if there is more, or the function. When
the function returns, the :around
advice code continues
execution. :do-it
may appear several times in
:around
advice. Normally, it is placed in conditional
code, e.g.
(if (zerop (car excl:arglist))(+ 5 :do-it)(* 7 :do-it))
In that case, the system will encounter one or the other
:do-it
, but not both. However, it is allowed to have
several :do-it
s all of which are evaluated. In that case,
the succeeding :around
advice and the advised function
are evaluated more than once. :after
advice is still
evaluated only once, however. :around
advice can work
with excl:arglist
before the :do-it
. Since
the advised function is run at the location specified by the
:do-it
, the values the function return are available to
:around
advice just like with any function call. The list
bound to the variable values
is not set up until after
all :around
advice is run, then values
is
bound to the list of values returned by the final piece of
:around
advice. Note that if the function returns
multiple values, these should be caught with multiple-value-bind or multiple-value-list or some similar function if
you are interested in the values beyond the first.
advice is evaluated after the function has completed, but before
control is passed back to whatever called the
function. :after
advice may examine and change the list
of returned values from the last piece of :around
advice
(or the function, if there is no :around
advice) stored
in the variable values
. :after
advice is
used only for its side effects. Any value returned by the
:after
advice code is ignored. The list bound to
values
is returned from the now completed function
call.
See also fwrappers-and-advice.htm for general information on the new fwrapper facility and the older, now deprecated, advice facility in Allegro CL.
The documentation is described in introduction.htm and the index is in index.htm.
Copyright (c) 1998-2000, Franz Inc. Berkeley, CA., USA. All rights reserved.
Created 2000.10.5.