1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-01-10 15:56:18 +00:00

* doc/misc/eieio.texi: Update to account for the cl-generic facilities

(Quick Start, Class Options, Generics): Adjust names for cl-generic.
(Methods): Document cl-defmethod.
Explain in more detail the order in which the various
methods are executed.  Document the conditions under which a method
is redefined.  Remove reference to `eieio-generic-call-arglst`.
Don't document the precise return value of cl-next-method-p.
(Static Methods): Adjust to use `subclass` specializer.
(Method Invocation): Use cl-call-next-method and drop mention of :primary.
(Signal Handling, Signals): Adjust names and args for cl-generic; add
cl-no-primary-method.
(CLOS compatibility, Wish List): Adjust to new featureset.
This commit is contained in:
Stefan Monnier 2017-02-28 11:11:01 -05:00
parent 8d7a3f4890
commit 0fa5941727

View File

@ -112,7 +112,7 @@ three slots named @code{name}, @code{birthday}, and @code{phone}:
Each class can have methods, which are defined like this:
@example
(defmethod call-record ((rec record) &optional scriptname)
(cl-defmethod call-record ((rec record) &optional scriptname)
"Dial the phone for the record REC.
Execute the program SCRIPTNAME to dial the phone."
(message "Dialing the phone for %s" (oref rec name))
@ -170,7 +170,7 @@ or
In these examples, @eieio{} automatically examines the class of
@code{rec}, and ensures that the method defined above is called. If
@code{rec} is some other class lacking a @code{call-record} method, or
some other data type, Emacs signals a @code{no-method-definition}
some other data type, Emacs signals a @code{cl-no-applicable-method}
error. @ref{Signals}.
@node Introduction
@ -589,9 +589,9 @@ This option is specific to Emacs, and is not in the CLOS spec.
@item :method-invocation-order
This controls the order in which method resolution occurs for
@code{:primary} methods in cases of multiple inheritance. The order
methods in cases of multiple inheritance. The order
affects which method is called first in a tree, and if
@code{call-next-method} is used, it controls the order in which the
@code{cl-call-next-method} is used, it controls the order in which the
stack of methods are run.
Valid values are:
@ -817,19 +817,19 @@ provides a function binding and the base documentation for the method
symbol (@pxref{Symbol Components,,,elisp,GNU Emacs Lisp Reference
Manual}).
@defmac defgeneric method arglist [doc-string]
@defmac cl-defgeneric method arglist [doc-string]
This macro turns the (unquoted) symbol @var{method} into a function.
@var{arglist} is the default list of arguments to use (not implemented
yet). @var{doc-string} is the documentation used for this symbol.
A generic function acts as a placeholder for methods. There is no
need to call @code{defgeneric} yourself, as @code{defmethod} will call
need to call @code{cl-defgeneric} yourself, as @code{cl-defmethod} will call
it if necessary. Currently the argument list is unused.
@code{defgeneric} signals an error if you attempt to turn an existing
@code{cl-defgeneric} signals an error if you attempt to turn an existing
Emacs Lisp function into a generic function.
You can also create a generic method with @code{defmethod}
You can also create a generic method with @code{cl-defmethod}
(@pxref{Methods}). When a method is created and there is no generic
method in place with that name, then a new generic will be created,
and the new method will use it.
@ -842,31 +842,26 @@ only occurs for the first argument, so the @var{arglist} is not used.
@node Methods
@section Methods
A method is a function that is executed if the first argument passed
to it matches the method's class. Different @eieio{} classes may
A method is a function that is executed if the arguments passed
to it matches the method's specializers. Different @eieio{} classes may
share the same method names.
Methods are created with the @code{defmethod} macro, which is similar
Methods are created with the @code{cl-defmethod} macro, which is similar
to @code{defun}.
@defmac defmethod method [:before | :primary | :after | :static ] arglist [doc-string] forms
@defmac cl-defmethod method [:before | :around | :after ] arglist [doc-string] forms
@var{method} is the name of the function to create.
@code{:before} and @code{:after} specify execution order (i.e., when
this form is called). If neither of these symbols are present, the
default priority is used (before @code{:after} and after
@code{:before}); this default priority is represented in CLOS as
@code{:primary}.
@code{:before}, @code{:around}, and @code{:after} specify execution order
(i.e., when this form is called). If none of these symbols are present, the
method is said to be a @emph{primary}.
@b{Note:} The @code{:BEFORE}, @code{:PRIMARY}, @code{:AFTER}, and
@code{:STATIC} method tags were in all capital letters in previous
versions of @eieio{}.
@var{arglist} is the list of arguments to this method. The first
argument in this list---and @emph{only} the first argument---may have
a type specifier (see the example below). If no type specifier is
supplied, the method applies to any object.
@var{arglist} is the list of arguments to this method. The mandatory arguments
in this list may have a type specializer (see the example below) which means
that the method will only apply when those arguments match the given type
specializer. An argument with no type specializer means that the method
applies regardless of its value.
@var{doc-string} is the documentation attached to the implementation.
All method doc-strings are incorporated into the generic method's
@ -881,7 +876,7 @@ In the following example, we create a method @code{mymethod} for the
@code{classname} class:
@example
(defmethod mymethod ((obj classname) secondarg)
(cl-defmethod mymethod ((obj classname) secondarg)
"Doc string" )
@end example
@ -889,84 +884,86 @@ In the following example, we create a method @code{mymethod} for the
This method only executes if the @var{obj} argument passed to it is an
@eieio{} object of class @code{classname}.
A method with no type specifier is a @dfn{default method}. If a given
A method with no type specializer is a @dfn{default method}. If a given
class has no implementation, then the default method is called when
that method is used on a given object of that class.
Only one default method per execution specifier (@code{:before},
@code{:primary}, or @code{:after}) is allowed. If two
@code{defmethod}s appear with @var{arglist}s lacking a type specifier,
and having the same execution specifier, then the first implementation
is replaced.
Only one method per combination of specializers and qualifiers (@code{:before},
@code{:around}, or @code{:after}) is kept. If two @code{cl-defmethod}s appear
with the same specializers and the same qualifiers, then the second
implementation replaces the first.
When a method is called on an object, but there is no method specified
for that object, but there is a method specified for object's parent
class, the parent class' method is called. If there is a method
class, the parent class's method is called. If there is a method
defined for both, only the child's method is called. A child method
may call a parent's method using @code{call-next-method}, described
may call a parent's method using @code{cl-call-next-method}, described
below.
If multiple methods and default methods are defined for the same
method and class, they are executed in this order:
@enumerate
@item method :before
@item default :before
@item method :primary
@item default :primary
@item method :after
@item default :after
@item :around methods
The most specific @code{:around} method is called first, which may invoke the
less specific ones via @code{cl-call-next-method}. If it doesn't invoke
@code{cl-call-next-method}, then no other methods will be executed. When there
are no more @code{:around} methods to call, falls through to run the other
(non-@code{:around}) methods.
@item :before methods
Called in sequence from most specific to least specific.
@item primary methods
The most specific method is called, which may invoke the less specific
ones via @code{cl-call-next-method}.
@item :after methods
Called in sequence from least specific to most specific.
@end enumerate
If no methods exist, Emacs signals a @code{no-method-definition}
error. @xref{Signals}.
If no methods exist, Emacs signals a @code{cl-no-applicable-method} error.
@xref{Signals}. If methods exist but none of them are primary, Emacs
signals a @code{cl-no-primary-method} error. @xref{Signals}.
@defun call-next-method &rest replacement-args
@anchor{call-next-method}
@defun cl-call-next-method &rest replacement-args
@anchor{cl-call-next-method}
This function calls the superclass method from a subclass method.
This is the ``next method'' specified in the current method list.
If @var{replacement-args} is non-@code{nil}, then use them instead of
@code{eieio-generic-call-arglst}. At the top level, the generic
argument list is passed in.
If @var{replacement-args} is non-@code{nil}, then use them instead of the
arguments originally provided to the method.
Use @code{next-method-p} to find out if there is a next method to
call.
Can only be used from within the lexical body of a primary or around method.
@end defun
@defun next-method-p
@anchor{next-method-p}
@defun cl-next-method-p
@anchor{cl-next-method-p}
Non-@code{nil} if there is a next method.
Returns a list of lambda expressions which is the @code{next-method}
order.
Can only be used from within the lexical body of a primary or around method.
@end defun
At present, @eieio{} does not implement all the features of CLOS:
@enumerate
@item
There is currently no @code{:around} tag.
@item
CLOS allows multiple sets of type-cast arguments, but @eieio{} only
allows the first argument to be cast.
@end enumerate
@node Static Methods
@section Static Methods
Static methods do not depend on an object instance, but instead
operate on a class. You can create a static method by using
the @code{:static} key with @code{defmethod}.
the @code{subclass} specializer with @code{cl-defmethod}:
The first argument of a @code{:static} method will be a class rather than an
@example
(cl-defmethod make-instance ((class (subclass mychild)) &rest args)
(let ((new (cl-call-next-method)))
(push new all-my-children)
new))
@end example
The first argument of a static method will be a class rather than an
object. Use the functions @code{oref-default} or @code{oset-default} which
will work on a class.
A class's @code{make-instance} method is defined as a @code{:static}
A class's @code{make-instance} method is defined as a static
method.
@b{Note:} The @code{:static} keyword is unique to @eieio{}.
@b{Note:} The @code{subclass} specializer is unique to @eieio{}.
@c TODO - Write some more about static methods here
@ -977,9 +974,9 @@ When classes are defined, you can specify the
@code{:method-invocation-order}. This is a feature specific to EIEIO.
This controls the order in which method resolution occurs for
@code{:primary} methods in cases of multiple inheritance. The order
methods in cases of multiple inheritance. The order
affects which method is called first in a tree, and if
@code{call-next-method} is used, it controls the order in which the
@code{cl-call-next-method} is used, it controls the order in which the
stack of methods are run.
The original EIEIO order turned out to be broken for multiple
@ -1297,8 +1294,7 @@ class.
@defmethod eieio-instance-tracker initialize-instance obj slot
This method is defined as an @code{:after} method.
It adds new instances to the master list. Do not overload this method
unless you use @code{call-next-method.}
It adds new instances to the master list.
@end defmethod
@defmethod eieio-instance-tracker delete-instance obj
@ -1582,7 +1578,7 @@ Additional useful methods defined on the base subclass are:
Make a copy of @var{obj}, and then apply @var{params}.
@var{params} is a parameter list of the same form as @var{initialize-instance}
which are applied to change the object. When overloading @dfn{clone}, be
sure to call @dfn{call-next-method} first and modify the returned object.
sure to call @dfn{cl-call-next-method} first and modify the returned object.
@end defun
@defun object-print this &rest strings
@ -1595,7 +1591,7 @@ It is sometimes useful to put a summary of the object into the
default #<notation> string when using eieio browsing tools.
Implement this function and specify @var{strings} in a call to
@dfn{call-next-method} to provide additional summary information.
@dfn{cl-call-next-method} to provide additional summary information.
When passing in extra strings from child classes, always remember
to prepend a space.
@ -1604,10 +1600,11 @@ to prepend a space.
(value)
"Object containing one data slot.")
(defmethod object-print ((this data-object) &optional strings)
(cl-defmethod object-print ((this data-object) &optional strings)
"Return a string with a summary of the data object as part of the name."
(apply 'call-next-method this
(cons (format " value: %s" (render this)) strings)))
(apply #'cl-call-next-method this
(format " value: %s" (render this))
strings))
@end example
Here is what some output could look like:
@ -1667,24 +1664,36 @@ In @var{clos}, the argument list is (@var{class} @var{object} @var{slot-name}),
@var{eieio} can only dispatch on the first argument, so the first two are swapped.
@end defun
@defun no-applicable-method object method &rest args
@anchor{no-applicable-method}
Called if there are no implementations for @var{object} in @var{method}.
@var{object} is the object which has no method implementation.
@var{args} are the arguments that were passed to @var{method}.
@defun cl-no-applicable-method generic &rest args
@anchor{cl-no-applicable-method}
Called if there are no methods applicable for @var{args} in the generic
function @var{generic}.
@var{args} are the arguments that were passed to @var{generic}.
Implement this for a class to block this signal. The return
value becomes the return value of the original method call.
@end defun
@defun no-next-method object &rest args
@anchor{no-next-method}
Called from @dfn{call-next-method} when no additional methods are available.
@var{object} is othe object being called on @dfn{call-next-method}.
@defun cl-no-primary-method generic &rest args
@anchor{cl-no-primary-method}
Called if there are methods applicable for @var{args} in the generic
function @var{generic} but they are all qualified.
@var{args} are the arguments that were passed to @var{generic}.
Implement this for a class to block this signal. The return
value becomes the return value of the original method call.
@end defun
@defun cl-no-next-method generic method &rest args
@anchor{cl-no-next-method}
Called from @dfn{cl-call-next-method} when no additional methods are available.
@var{generic} is the generic function being called on
@dfn{cl-call-next-method}, @var{method} is the method where
@dfn{cl-call-next-method} was called, and
@var{args} are the arguments it is called by.
This method signals @dfn{no-next-method} by default. Override this
This method signals @dfn{cl-no-next-method} by default. Override this
method to not throw an error, and its return value becomes the
return value of @dfn{call-next-method}.
return value of @dfn{cl-call-next-method}.
@end defun
@node Signals
@ -1699,23 +1708,29 @@ This signal is called when an attempt to reference a slot in an
it.
@end deffn
@deffn Signal no-method-definition method arguments
This signal is called when @var{method} is called, with @var{arguments}
and nothing is resolved. This occurs when @var{method} has been
@deffn Signal cl-no-applicable-method generic arguments
This signal is called when @var{generic} is called, with @var{arguments}
and nothing is resolved. This occurs when @var{generic} has been
defined, but the arguments make it impossible for @eieio{} to determine
which method body to run.
To prevent this signal from occurring in your class, implement the
method @code{no-applicable-method} for your class. This method is
method @code{cl-no-applicable-method} for your class. This method is
called when to throw this signal, so implementing this for your class
allows you block the signal, and perform some work.
@end deffn
@deffn Signal no-next-method class arguments
This signal is called if the function @code{call-next-method} is called
@deffn Signal cl-no-primary-method generic arguments
Like @code{cl-no-applicable-method} but applies when there are some applicable
methods, but none of them are primary. You can similarly block it by
implementing a @code{cl-no-primary-method} method.
@end deffn
@deffn Signal cl-no-next-method class arguments
This signal is called if the function @code{cl-call-next-method} is called
and there is no next method to be called.
Overload the method @code{no-next-method} to protect against this signal.
Overload the method @code{cl-no-next-method} to protect against this signal.
@end deffn
@deffn Signal invalid-slot-type slot spec value
@ -1796,22 +1811,17 @@ Make instance works as expected, however it just uses the @eieio{} instance
creator automatically generated when a new class is created.
@xref{Making New Objects}.
@item defgeneric
Creates the desired symbol, and accepts all of the expected arguments
except @code{:around}.
@item cl-defgeneric
Creates the desired symbol, and accepts most of the expected arguments of
CLOS's @code{defgeneric}.
@item defmethod
Calls defgeneric, and accepts most of the expected arguments. Only
the first argument to the created method may have a type specifier.
To type cast against a class, the class must exist before defmethod is
called. In addition, the @code{:around} tag is not supported.
@item cl-defmethod
Accepts most of the expected arguments of CLOS's @code{defmethod}. To type
cast against a class, the class must exist before @code{cl-defmethod}
is called.
@item call-next-method
Inside a method, calls the next available method up the inheritance tree
for the given object. This is different than that found in CLOS because
in @eieio{} this function accepts replacement arguments. This permits
subclasses to modify arguments as they are passed up the tree. If no
arguments are given, the expected CLOS behavior is used.
@item cl-call-next-method
Works just like CLOS's @code{call-next-method}.
@end table
CLOS supports the @code{describe} command, but @eieio{} provides
@ -1834,13 +1844,7 @@ Some important compatibility features that would be good to add are:
@enumerate
@item
Support for metaclasses and EQL specialization.
@item
@code{:around} method key.
@item
Method dispatch for built-in types.
@item
Method dispatch for multiple argument typing.
Support for metaclasses.
@item
Improve integration with the @file{cl} package.
@end enumerate