Next: Dynamic-Extent Declarations, Previous: Differences from ANSI Common Lisp, Up: Design Choices and Extensions [Contents][Index]
Function wrappers, fwrappers for short, are a facility for efficiently encapsulating functions3.
Functions in CMUCL are represented by kernel:fdefn
objects. Each fdefn
object contains a reference to its
function’s actual code, which we call the function’s primary function.
A function wrapper replaces the primary function in the fdefn
object with a function of its own, and records the original function
in an fwrapper object, a funcallable instance. Thus, when the
function is called, the fwrapper gets called, which in turn might call
the primary function, or a previously installed fwrapper that was
found in the fdefn
object when the second fwrapper was
installed.
Example:
(use-package :fwrappers) (define-fwrapper foo (x y) (format t "x = ~s, y = ~s, user-data = ~s~%" x y (fwrapper-user-data fwrapper)) (let ((value (call-next-function))) (format t "value = ~s~%" value) value)) (defun bar (x y) (+ x y)) (fwrap 'bar #'foo :type 'foo :user-data 42) (bar 1 2) => x = 1, y = 2, user-data = 42 value = 3 3
Fwrappers are used in the implementation of trace
and
profile
.
Please note that fdefinition
always returns the primary
definition of a function; if a function is fwrapped,
fdefinition
returns the primary function stored in the
innermost fwrapper object. Likewise, if a function is fwrapped,
(setf fdefinition)
will set the primary function in the
innermost fwrapper.
This macro is like defun
, but defines a function named
name that can be used as an fwrapper definition.
In body, the symbol fwrapper
is bound to the current
fwrapper object.
The macro call-next-function
can be used to invoke the next
fwrapper, or the primary function that is being fwrapped. When
called with no arguments, call-next-function
invokes the next
function with the original arguments passed to the fwrapper, unless
you modify one of the parameters. When called with arguments,
call-next-function
invokes the next function with the given
arguments.
:type
:user-data
¶This function wraps function function-name
in an fwrapper
fwrapper which was defined with define-fwrapper
.
The value of type, if supplied, is used as an identifying tag that can be used in various other operations.
The value of user-data is stored as user-supplied data in the
fwrapper object that is created for the function encapsulation.
User-data is accessible in the body of fwrappers defined with
define-fwrapper
as (fwrapper-user-data fwrapper)
.
Value is the fwrapper object created.
:type
:test
¶Remove fwrappers from the function named function-name. If
type is supplied, remove fwrappers whose type is equal
to type. If test is supplied, remove fwrappers
satisfying test.
:type
:test
¶Find an fwrapper of function-name. If type is supplied,
find an fwrapper whose type is equal
to type. If
test is supplied, find an fwrapper satisfying test.
Update the funcallable instance function of the fwrapper object
fwrapper from the definition of its function that was
defined with define-fwrapper
. This can be used to update
fwrappers after changing a define-fwrapper
.
:type
:test
¶Update fwrappers of function-name; see update-fwrapper
.
If type is supplied, update fwrappers whose type is
equal
to type. If test is supplied, update fwrappers
satisfying test.
Set function-names’s fwrappers to elements of the list fwrappers, which is assumed to be ordered from outermost to innermost. fwrappers null means remove all fwrappers.
Return a list of all fwrappers of function-name, ordered from outermost to innermost.
Prepend fwrapper fwrapper to the definition of function-name. Signal an error if function-name is an undefined function.
Remove fwrapper fwrapper from the definition of function-name. Signal an error if function-name is an undefined function.
&optional
result) &body body ¶Evaluate body with var bound to consecutive fwrappers of
fdefn. Return result at the end. Note that fdefn
must be an fdefn
object. You can use
kernel:fdefn-or-lose
, for instance, to get the fdefn
object from a function name.
This feature was independently developed, but the interface is modelled after a similar feature in Allegro. Some names, however, have been changed.
Next: Dynamic-Extent Declarations, Previous: Differences from ANSI Common Lisp, Up: Design Choices and Extensions [Contents][Index]