Function: cl-defmethod
cl-defmethod is a macro defined in cl-generic.el.gz.
Signature
(cl-defmethod NAME [EXTRA] [QUALIFIER] ARGS &rest [DOCSTRING] BODY)
Documentation
Define a new method for generic function NAME.
This defines an implementation of NAME to use for invocations of specific types of arguments.
ARGS is a list of dispatch arguments (see cl-defun), but where
each variable element is either just a single variable name VAR,
or a list on the form (VAR TYPE).
For instance:
(cl-defmethod foo (bar (format-string string) &optional zot)
(format format-string bar))
The dispatch arguments have to be among the mandatory arguments, and all methods of NAME have to use the same set of arguments for dispatch. Each dispatch argument and TYPE are specified in ARGS where the corresponding formal argument appears as (VAR TYPE) rather than just VAR.
The optional EXTRA element, on the form :extra STRING, allows you to add more methods for the same specializers and qualifiers. These are distinguished by STRING.
The optional argument QUALIFIER is a specifier that modifies how
the method is combined with other methods, including:
:before - Method will be called before the primary
:after - Method will be called after the primary
:around - Method will be called around everything else
The absence of QUALIFIER means this is a "primary" method.
The set of acceptable qualifiers and their meaning is defined
(and can be extended) by the methods of cl-generic-combine-methods.
ARGS can also include so-called context specializers, introduced by
&context (which should appear right after the mandatory arguments,
before any &optional or &rest). They have the form (EXPR TYPE) where
EXPR is an Elisp expression whose value should match TYPE for the
method to be applicable.
The set of acceptable TYPEs (also called "specializers") is defined
(and can be extended) by the various methods of cl-generic-generalizers.
Currently supported forms for TYPE:
Support for the catch-all t specializer which always matches.
Support for (eql VAL) specializers.
These match if the argument is eql to VAL.
Support for (derived-mode MODE) specializers. Used internally for the (major-mode MODE) context specializers.
Support for (subclass CLASS) specializers. These match if the argument is the name of a subclass of CLASS.
Probably introduced at or before Emacs version 25.1.
Source Code
;; Defined in /usr/src/emacs/lisp/emacs-lisp/cl-generic.el.gz
;;;###autoload
(defmacro cl-defmethod (name args &rest body)
"Define a new method for generic function NAME.
This defines an implementation of NAME to use for invocations
of specific types of arguments.
ARGS is a list of dispatch arguments (see `cl-defun'), but where
each variable element is either just a single variable name VAR,
or a list on the form (VAR TYPE).
For instance:
(cl-defmethod foo (bar (format-string string) &optional zot)
(format format-string bar))
The dispatch arguments have to be among the mandatory arguments, and
all methods of NAME have to use the same set of arguments for dispatch.
Each dispatch argument and TYPE are specified in ARGS where the corresponding
formal argument appears as (VAR TYPE) rather than just VAR.
The optional EXTRA element, on the form `:extra STRING', allows
you to add more methods for the same specializers and qualifiers.
These are distinguished by STRING.
The optional argument QUALIFIER is a specifier that modifies how
the method is combined with other methods, including:
:before - Method will be called before the primary
:after - Method will be called after the primary
:around - Method will be called around everything else
The absence of QUALIFIER means this is a \"primary\" method.
The set of acceptable qualifiers and their meaning is defined
\(and can be extended) by the methods of `cl-generic-combine-methods'.
ARGS can also include so-called context specializers, introduced by
`&context' (which should appear right after the mandatory arguments,
before any &optional or &rest). They have the form (EXPR TYPE) where
EXPR is an Elisp expression whose value should match TYPE for the
method to be applicable.
The set of acceptable TYPEs (also called \"specializers\") is defined
\(and can be extended) by the various methods of `cl-generic-generalizers'.
\(fn NAME [EXTRA] [QUALIFIER] ARGS &rest [DOCSTRING] BODY)"
(declare (doc-string cl--defmethod-doc-pos) (indent defun)
(debug
(&define ; this means we are defining something
[&name [sexp ;Allow (setf ...) additionally to symbols.
[&rest cl-generic--method-qualifier-p] ;qualifiers
listp] ; arguments
cl--generic-edebug-make-name nil]
lambda-doc ; documentation string
def-body))) ; part to be debugged
(let ((qualifiers nil))
(while (cl-generic--method-qualifier-p args)
(push args qualifiers)
(setq args (pop body)))
(when (eq 'setf (car-safe name))
(require 'gv)
(declare-function gv-setter "gv" (name))
(setq name (gv-setter (cadr name))))
(pcase-let* ((`(,call-con . ,fun) (cl--generic-lambda args body)))
`(progn
;; You could argue that `defmethod' modifies rather than defines the
;; function, so warnings like "not known to be defined" are fair game.
;; But in practice, it's common to use `cl-defmethod'
;; without a previous `cl-defgeneric'.
;; The ",'" is a no-op that pacifies check-declare.
(,'declare-function ,name "")
;; We use #' to quote `name' so as to trigger an
;; obsolescence warning when applicable.
(cl-generic-define-method #',name ',(nreverse qualifiers) ',args
',call-con ,fun)))))