Homepage: https://www.gnu.org/software/emacs
Author: Stefan Monnier
CLOS-style generic functions for Elisp
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 `eval'uated 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) - (head ) which checks that the arg is a cons with 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 ). - 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).