Emacs provides support for polymorphism, supporting "generic functions", like in CLOS.
According to Emacs manual:

A generic function specifies an abstract operation, by defining its name and list of arguments, but (usually) no implementation. The actual implementation for several specific classes of arguments is provided by "methods", which should be defined separately [...] by “specializing” the arguments defined by the generic function.

Unfortunately the manual does not give practical examples of a methods implementation once a generic function is defined. Can you give such an example, implementing the standard OO paradigms through cl-defgeneric/cl-defmethod?

  • 2
    The elisp manual has a decent amount to say about them. C-h i g (elisp) Generic Functions. Always check the manual.
    – phils
    Sep 28 '16 at 22:56
  • 2
    You could look at Common Lisp docs (such as the hyperspec).
    – Qudit
    Sep 28 '16 at 23:24
  • 1
    If you do not find the doc to be as helpful as you think it should be please consider reporting that as a doc bug/suggestion: M-x report-emacs-bug.
    – Drew
    Sep 29 '16 at 0:03
  • 1
    In general, I think the doc for CL stuff in Emacs is pretty poor. Typically, you need to consult the Common Lisp doc, and then sometimes try to figure out how the Emacs-Lisp implementation might differ.
    – Drew
    Sep 29 '16 at 0:04
  • 1
    No examples (my comment wasn't intended as an answer); but you said you were "unable to find documentation" apart from the docstrings, and that manual page contains rather more information than the docstrings. Reminding you that the manual is a thing that exists seemed fairly useful.
    – phils
    Sep 29 '16 at 20:36

An attempt...

(require 'cl-generic)

;; Checking accounts can have a negative balance
;; Savings accounts can't
(cl-defstruct checking-account balance)
(cl-defstruct savings-account balance)

;; A generic `withdraw' method
(cl-defgeneric withdraw (account amount)    
  (:documentation "Withdraw AMOUNT from ACCOUNT balance.
Give an error for savings accounts where balance < AMOUNT"))

;; Implementation of `withdraw' for checking accounts
(cl-defmethod withdraw ((account checking-account) amount)
  (cl-decf (checking-account-balance account) amount))

;; Implementation of `withdraw' for savings accounts
(cl-defmethod withdraw ((account savings-account) amount)
  (when (< (savings-account-balance account) amount)
    (error "Account overdrawn."))
  (cl-decf (savings-account-balance account) amount))

;; Account instantiations, i.e. creation of account objects  
(setq x (make-checking-account :balance 50))
(setq y (make-savings-account :balance 50))

;; Withdraw amounts from accounts 
(withdraw x 60) ; => - 10
(withdraw y 60) ; => (error "Account overdrawn.")

See gigamonkeys.com for Common Lisp.

  • You might want to amend or extend this example to improve readability or effectiveness.
    – antonio
    Sep 29 '16 at 14:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.