$Revision: 5.0.2.5 $
Package: EXCL
Arguments: (fspec class name position
&rest forms)
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 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 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.
: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 cl:multiple-value-bind
or cl: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 advice.htm for general information on the advice facility in Allegro CL.
The general documentation description is in introduction.htm. The index in index.htm.
Copyright (C) 1998-1999, Franz Inc., Berkeley, CA. All Rights Reserved.