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-memoizationTable storing previously built combined-methods.

Defined functions (91)

cl--defmethod-doc-pos()
cl--generic(NAME)
cl--generic-arg-specializer(METHOD DISPATCH-ARG)
cl--generic-build-combined-method(GENERIC METHODS)
cl--generic-cache-miss(GENERIC DISPATCH-ARG DISPATCHES-LEFT METHODS-LEFT TYPES)
cl--generic-derived-specializers(MODE &rest _)
cl--generic-describe(FUNCTION)
cl--generic-dispatches(CL-X)
cl--generic-dispatches--cmacro(CL-WHOLE-ARG CL-X)
cl--generic-edebug-make-name(IN:METHOD OLDNAME &rest QUALS-AND-ARGS)
cl--generic-edebug-remember-name(NAME PF &rest SPECS)
cl--generic-generalizer-name(CL-X)
cl--generic-generalizer-name--cmacro(CL-WHOLE-ARG CL-X)
cl--generic-generalizer-p(CL-X)
cl--generic-generalizer-p--cmacro(CL-WHOLE-ARG CL-X)
cl--generic-generalizer-priority(CL-X)
cl--generic-generalizer-priority--cmacro(CL-WHOLE-ARG CL-X)
cl--generic-generalizer-specializers-function(CL-X)
cl--generic-generalizer-specializers-function--cmacro(CL-WHOLE-ARG CL-X)
cl--generic-generalizer-tagcode-function(CL-X)
cl--generic-generalizer-tagcode-function--cmacro(CL-WHOLE-ARG CL-X)
cl--generic-get-dispatcher(DISPATCH)
cl--generic-isnot-nnm-p(CNM)
cl--generic-lambda(ARGS BODY)
cl--generic-load-hist-format(NAME QUALIFIERS SPECIALIZERS)
cl--generic-make(NAME)
cl--generic-make--cmacro(CL-WHOLE-ARG NAME)
cl--generic-make-function(GENERIC)
cl--generic-make-method(SPECIALIZERS QUALIFIERS CALL-CON FUNCTION)
cl--generic-make-method--cmacro(CL-WHOLE-ARG SPECIALIZERS QUALIFIERS CALL-CON FUNCTION)
cl--generic-make-next-function(GENERIC DISPATCHES METHODS)
cl--generic-member-method(SPECIALIZERS QUALIFIERS METHODS)
cl--generic-method-call-con(CL-X)
cl--generic-method-call-con--cmacro(CL-WHOLE-ARG CL-X)
cl--generic-method-documentation(FUNCTION TYPE)
cl--generic-method-files(METHOD)
cl--generic-method-function(CL-X)
cl--generic-method-function--cmacro(CL-WHOLE-ARG CL-X)
cl--generic-method-info(METHOD)
cl--generic-method-qualifiers(CL-X)
cl--generic-method-qualifiers--cmacro(CL-WHOLE-ARG CL-X)
cl--generic-method-specializers(CL-X)
cl--generic-method-specializers--cmacro(CL-WHOLE-ARG CL-X)
cl--generic-method-table(CL-X)
cl--generic-method-table--cmacro(CL-WHOLE-ARG CL-X)
cl--generic-name(CL-X)
cl--generic-name--cmacro(CL-WHOLE-ARG CL-X)
cl--generic-nnm--internal-p(OCLOSURE)
cl--generic-oclosure-tag(NAME &rest _)
cl--generic-options(CL-X)
cl--generic-options--cmacro(CL-WHOLE-ARG CL-X)
cl--generic-prefill-generalizer-sample(X)
cl--generic-search-method(MET-NAME)
cl--generic-specializers-apply-to-type-p(SPECIALIZERS TYPE)
cl--generic-split-args(ARGS)
cl--generic-standard-method-combination(GENERIC METHODS)
cl--generic-type-specializers(TAG &rest _)
cl--generic-upcase-formal-args(ARGS)
cl--map-methods-documentation(FUNNAME METNAME-PRINTER)
cl--struct-cl--generic-method-p(CL-X)
cl--struct-cl--generic-method-p--cmacro(CL-WHOLE-ARG CL-X)
cl--struct-cl--generic-p(CL-X)
cl--struct-cl--generic-p--cmacro(CL-WHOLE-ARG CL-X)
cl-call-next-method(&rest ARGS)
cl-defgeneric(NAME ARGS [DOC-STRING] [OPTIONS-AND-METHODS...] &rest DEFAULT-BODY)
cl-defmethod(NAME [EXTRA] [QUALIFIER] ARGS &rest [DOCSTRING] BODY)
cl-find-method(GENERIC QUALIFIERS SPECIALIZERS)
cl-generic--method-qualifier-p(X)
cl-generic-all-functions(&optional TYPE)
cl-generic-apply(GENERIC ARGS)
cl-generic-call-method(GENERIC METHOD &optional FUN)
cl-generic-combine-methods(GENERIC METHODS)
cl-generic-current-method-specializers()
cl-generic-define(NAME ARGS OPTIONS)
cl-generic-define-context-rewriter(NAME ARGS &rest BODY)
cl-generic-define-generalizer(NAME PRIORITY TAGCODE-FUNCTION SPECIALIZERS-FUNCTION)
cl-generic-define-method(NAME QUALIFIERS ARGS CALL-CON FUNCTION)
cl-generic-ensure-function(NAME &optional NOERROR)
cl-generic-function-options(GENERIC)
cl-generic-generalizers(SPECIALIZER)
cl-generic-make-generalizer(NAME PRIORITY TAGCODE-FUNCTION SPECIALIZERS-FUNCTION)
cl-generic-make-generalizer--cmacro(CL-WHOLE-ARG NAME PRIORITY TAGCODE-FUNCTION SPECIALIZERS-FUNCTION)
cl-generic-p(F)
cl-method-qualifiers(CL-X)
cl-next-method-p()
cl-no-applicable-method(GENERIC &rest ARGS)
cl-no-next-method(GENERIC METHOD &rest ARGS)
cl-no-primary-method(GENERIC &rest ARGS)
copy-cl--generic(ARG)
copy-cl--generic-generalizer(ARG)
copy-cl--generic-method(ARG)

Defined faces (0)