Next: , Previous: , Up: Design Choices and Extensions   [Contents][Index]


2.25 Function Wrappers

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.

Macro: fwrappers:define-fwrapper name lambda-list &body body

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.

Function: fwrappers:fwrap function-name fwrapper &key :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.

Function: fwrappers:funwrap function-name &key :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.

Function: fwrappers:find-fwrapper function-name &key :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.

Function: fwrappers:update-fwrapper fwrapper

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.

Function: fwrappers:update-fwrappers function-name &key :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.

Function: fwrappers:set-fwrappers function-name fwrappers

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.

Function: fwrappers:list-fwrappers function-name

Return a list of all fwrappers of function-name, ordered from outermost to innermost.

Function: fwrappers:push-fwrapper fwrapper function-name

Prepend fwrapper fwrapper to the definition of function-name. Signal an error if function-name is an undefined function.

Function: fwrappers:delete-fwrapper fwrapper function-name

Remove fwrapper fwrapper from the definition of function-name. Signal an error if function-name is an undefined function.

Macro: fwrappers:do-fwrappers (var fdefn &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.


Footnotes

(3)

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]