File: cl-generic.el.html
This implements most of CLOS's multiple-dispatch generic functions.
To use it you need either (require 'cl-generic) or (require 'cl-lib).
The main entry points are: cl-defgeneric and cl-defmethod.
Missing elements:
- We don't support make-method, call-method, define-method-combination.
CLOS's define-method-combination is IMO overly complicated, and it suffers
from a significant problem: the method-combination code returns a sexp
that needs to be evaluated or compiled. IOW it requires run-time
code generation. Given how rarely method-combinations are used,
I just provided a cl-generic-combine-methods generic function, to which
people can add methods if they are really desperate for such functionality.
- In defgeneric we don't support the options:
declare, :method-combination, :generic-function-class, :method-class.
Added elements:
- We support aliases to generic functions.
- cl-generic-generalizers. This generic function lets you extend the kind
of thing on which to dispatch. There is support in this file for
dispatch on:
- (eql <val>)
- (head <val>) which checks that the arg is a cons with <val> as its head.
- plain old types
- type of CL structs
eieio-core adds dispatch on:
- class of eieio objects
- actual class argument, using the syntax (subclass <class>).
- cl-generic-combine-methods (i.s.o define-method-combination and
compute-effective-method).
- cl-generic-call-method (which replaces make-method and call-method).
- The standard method combination supports ":extra STRING" qualifiers
which simply allows adding more methods for the same
specializers&qualifiers.
- Methods can dispatch on the context. For that, a method needs to specify
context arguments, introduced by &context (which need to come right
after the mandatory arguments and before anything like
&optional/&rest/&key). Each context argument is given as (EXP SPECIALIZER)
which means that EXP is taken as an expression which computes some context
and this value is then used to dispatch.
E.g. (foo &context (major-mode (eql c-mode))) is an arglist specifying
that this method will only be applicable when major-mode has value
c-mode.
Efficiency considerations: overall, I've made an effort to make this fairly
efficient for the expected case (e.g. no constant redefinition of methods).
- Generic functions which do not dispatch on any argument are implemented
optimally (just as efficient as plain old functions).
- Generic functions which only dispatch on one argument are fairly efficient
(not a lot of room for improvement without changes to the byte-compiler,
I think).
- Multiple dispatch is implemented rather naively. There's an extra apply
function call for every dispatch; we don't optimize each dispatch
based on the set of candidate methods remaining; we don't optimize the
order in which we performs the dispatches either;
If/when this becomes a problem, we can try and optimize it.
- call-next-method could be made more efficient, but isn't too terrible.
TODO:
- A generic "filter" generalizer (e.g. could be used to cleanly add methods
to cl-generic-combine-methods with a specializer that says it applies only
when some particular qualifier is used).
Defined variables (1)
cl--generic-combined-method-memoization | Table storing previously built combined-methods. |