* Function Cells:: Accessing or setting the function definition
of a symbol.
* Closures:: Functions that enclose a lexical environment.
-* OClosures:: Function objects
+* OClosures:: Function objects with meta-data.
* Advising Functions:: Adding to the definition of a function.
* Obsolete Functions:: Declaring functions obsolete.
* Inline Functions:: Functions that the compiler will expand inline.
@node OClosures
@section Open Closures
+@cindex oclosures
+@cindex open closures
-Traditionally, functions are opaque objects which offer no other
-functionality but to call them. Emacs Lisp functions aren't fully
+ Traditionally, functions are opaque objects which offer no other
+functionality but to call them. (Emacs Lisp functions aren't fully
opaque since you can extract some info out of them such as their
docstring, their arglist, or their interactive spec, but they are
-mostly opaque. This is usually what we want, but occasionally we need
-functions to expose a bit more information about themselves.
+still mostly opaque.) This is usually what we want, but occasionally
+we need functions to expose a bit more information about themselves.
-OClosures are functions which carry additional type information,
-and expose some information in the form of slots which you can access
+ @dfn{Open closures}, or @dfn{OClosures} for short, are function
+objects which carry additional type information and expose some
+information about themselves in the form of slots which you can access
via accessor functions.
-They are defined in two steps: first @code{oclosure-define} is used to
-define new OClosure types by specifying the slots carried by those
-OClosures, and then @code{oclosure-lambda} is used to create an
-OClosure object of a given type.
+ OClosures are defined in two steps: first you use
+@code{oclosure-define} to define a new OClosure type by specifying the
+slots carried by the OClosures of this type, and then you use
+@code{oclosure-lambda} to create an OClosure object of a given type.
+
+Let's say we want to define keyboard macros, i.e.@: interactive
+functions which re-execute a sequence of key events (@pxref{Keyboard
+Macros}). You could do it with a plain function as follows:
-Say we want to define keyboard macros, i.e. interactive functions
-which re-execute a sequence of key events. You could do it with
-a plain function as follows:
@example
(defun kbd-macro (key-sequence)
(lambda (&optional arg)
(interactive "P")
(execute-kbd-macro key-sequence arg)))
@end example
+
+@noindent
But with such a definition there is no easy way to extract the
@var{key-sequence} from that function, for example to print it.
We can solve this problem using OClosures as follows. First we define
the type of our keyboard macros (to which we decided to add
a @code{counter} slot while at it):
+
@example
(oclosure-define kbd-macro
"Keyboard macro."
keys (counter :mutable t))
@end example
+
+@noindent
After which we can rewrite our @code{kbd-macro} function:
+
@example
(defun kbd-macro (key-sequence)
(oclosure-lambda (kbd-macro (keys key-sequence) (counter 0))
(&optional arg)
- (interactive "p")
+ (interactive "P")
(execute-kbd-macro keys arg)
(setq counter (1+ counter))))
@end example
+
+@noindent
As you can see, the @code{keys} and @code{counter} slots of the
OClosure can be accessed as local variables from within the body
of the OClosure. But we can now also access them from outside of the
body of the OClosure, for example to describe a keyboard macro:
+
@example
(defun describe-kbd-macro (km)
(if (not (eq 'kbd-macro (oclosure-type km)))
(counter (kbd-macro--counter km)))
(message "Keys=%S, called %d times" keys counter))))
@end example
+
+@noindent
Where @code{kbd-macro--keys} and @code{kbd-macro--counter} are
-accessor functions generated by the @code{oclosure-define} macro.
+accessor functions generated by the @code{oclosure-define} macro for
+oclosures whose type is @code{kbd-macro}.
-@defmac oclosure-define name &optional docstring &rest slots
+@defmac oclosure-define oname &optional docstring &rest slots
This macro defines a new OClosure type along with accessor functions
-for its slots. @var{name} can be a symbol (the name of
-the new type), or a list of the form @code{(@var{name} . @var{type-props})} in
-which case @var{type-props} is a list of additional properties.
-@var{slots} is a list of slot descriptions where each slot can be
-either a symbol (the name of the slot) or it can be of the form
-@code{(@var{slot-name} . @var{slot-props})} where @var{slot-props} is
-a property list.
-
-For each slot, the macro creates an accessor function named
-@code{@var{name}--@var{slot-name}}. By default slots are immutable.
-If you need a slot to be mutable, you need to specify it with the
-@code{:mutable} slot property, after which it can be mutated for
-example with @code{setf}.
-
-Beside slot accessors, the macro can create a predicate and
-functional update functions according to @var{type-props}:
-a @code{(:predicate @var{pred-name})} in the @var{type-props} causes
-the definition of a predicate function under the name @var{pred-name},
-and @code{(:copier @var{copier-name} @var{copier-arglist})} causes the
-definition of a functional update function which takes an OClosure of
-type @var{name} as first argument and returns a copy of it with the
-slots named in @var{copier-arglist} modified to the value passed in the
-corresponding argument.
+for its @var{slots}. @var{oname} can be a symbol (the name of the new
+type), or a list of the form
+@w{@code{(@var{oname} . @var{type-props})}}, in which case
+@var{type-props} is a list of additional properties of this oclosure
+type. @var{slots} is a list of slot descriptions where each slot can
+be either a symbol (the name of the slot) or it can be of the form
+@w{@code{(@var{slot-name} . @var{slot-props})}}, where
+@var{slot-props} is a property list of the corresponding slot
+@var{slot-name}.
+The OClosure type's properties specified by @var{type-props} can
+include the following:
+
+@table @code
+@item (:predicate @var{pred-name})
+This requests creation of a predicate function named @var{pred-name}.
+This function will be used to recognize OClosures of the type
+@var{oname}. If this type property is not specified,
+@code{oclosure-define} will generate a default name for the
+predicate.
+@item (:parent @var{otype})
+This makes type @var{otype} of OClosures be the parent of the type
+@var{oname}. The OClosures of type @var{oname} inherit the
+@var{slots} defined by their parent type.
+@c FIXME: Is the above description of :parent correct?
+@item (:copier @var{copier-name} @var{copier-args})
+This causes the definition of a functional update function, knows as
+the @dfn{copier}, which takes an OClosure of type @var{oname} as its
+first argument and returns a copy of it with the slots named in
+@var{copier-args} modified to contain the value passed in the
+corresponding argument in the actual call to @var{copier-name}.
+@end table
+
+For each slot in @var{slots}, the @code{oclosure-define} macro creates
+an accessor function named @code{@var{oname}--@var{slot-name}}; these
+can be used to access the values of the slots. The slot definitions
+in @var{slots} can specify the following properties of the slots:
+
+@table @code
+@item :mutable @var{val}
+By default, slots are immutable, but if you specify the
+@code{:mutable} property with a non-@code{nil} value, the slot can be
+mutated, for example with @code{setf} (@pxref{Setting Generalized
+Variables}).
+@c FIXME: Some rationale and meaning of immutable slot is probably in
+@c order here.
+@item :type @var{val-type}
+This specifies the type of the values expected to appear in the slot.
+@c FIXME: What will happen if the value is of a different type? error?
+@end table
@end defmac
@defmac oclosure-lambda (type . slots) arglist &rest body
-This macro creates an anonymous OClosure of type @var{type}.
-@var{slots} should be a list of elements of the form @code{(@var{slot-name}
-@var{exp})}.
-At run time, each @var{exp} is evaluated, in order, after which
-the OClosure is created with its slots initialized with the
-resulting values.
-
-When called as a function, the OClosure will accept arguments
-according to @var{arglist} and will execute the code in @var{body}.
-@var{body} can refer to the value of any of its slot directly as if it
-were a local variable that had been captured by static scoping.
+This macro creates an anonymous OClosure of type @var{type}, which
+should have been defined with @code{oclosure-define}. @var{slots}
+should be a list of elements of the form
+@w{@code{(@var{slot-name} @var{expr})}}. At run time, each @var{expr}
+is evaluated, in order, after which the OClosure is created with its
+slots initialized with the resulting values.
+
+When called as a function (@pxref{Calling Functions}), the OClosure
+created by this macro will accept arguments according to @var{arglist}
+and will execute the code in @var{body}. @var{body} can refer to the
+value of any of its slot directly as if it were a local variable that
+had been captured by static scoping.
@end defmac
@defun oclosure-type object
-This function returns the OClosure type (a symbol) of @var{object} if it is an
-OClosure, and @code{nil} otherwise.
+This function returns the OClosure type (a symbol) of @var{object} if
+it is an OClosure, and @code{nil} otherwise.
@end defun