Clojure-style multi-methods for Emacs Lisp.
A multi-method is the combination of a dispatch function, and one or more methods. When a multi-method is applied, the dispatching function is first applied to the given arguments, and its return value is used to select the correct method branch to apply. A default method branch may be defined, which will be applied if none of the branches match.
Note: Multi requires lexical binding, thus it's only compatible with Emacs 24+
(require 'multi) (defmulti area (x &rest _) "Calculates the area of a geometric shape." x) (defmulti-method area 'rect (_ w h) (* w h)) (defmulti-method area 'circle (_ r) (* float-pi (* r r))) (defmulti-method-fallback area (&rest _) 'oops) (area 'rect 4 13) ;; => 52 (area 'circle 12) ;; => 452.3893421169302 (area 'sphere 12) ;; => 'oops
M-x package-install multi
Alternatively you can just dump
multi.el somewhere in your load path.
Using in a package
(multi "2.0.1") to your package requires. E.g.:
;; Package-Requires: ((multi "2.0.1"))
This package provides a form of polymorphism by way of predicate dispatching. Methods consist of a dispatch function, and a series of branches. The dispatch function is applied to the arguments, and the result value is checked against the expectations of each branch to define which one to invoke.
A default branch may be defined for a multi-method, and will be invoked if none of the defined cases match the result of applying the dispatch function. Branches may be defined or removed at any point in time, but it's an error to define a branch that has the same expectations of an existing one.
defmulti (name arguments [docstring] . body)
macro defmulti :: (Id, [Id], ...Form) → Unit macro defmulti :: (Id, [Id], String, ...Form) → Unit
Defines a new multi-method with the given name, and using the specified dispatch rules. A generic function is defined in the global table with the given name.
defun, an optional docstring may be given after the list of
defmulti-method (name premise arguments . body)
macro defmulti-method :: (Id, a, [Id], ...Form) → Unit
Defines a new branch for the multi-method with the given name. The
branch is applied whenever the multi-method dispatching function returns
a value that matches the
It's an error to provide a
promise that's already being used for some
other branch in the same multi-method.
defmulti-method-fallback (name arguments . body)
macro defmulti-method-fallback :: (Id, [Id], ...Form) → Unit
Replaces the default branch for the multi-method. The default branch is applied when none of the branches specified for a multi-method matches the dispatch value.
The default behaviour is to throw an exception.
multi-remove-method (name premise)
fun multi-remove-method :: (Id, a) → Unit
Removes the branch that matches the given
premise from the
fun multi-remove-method-fallback :: Id → Unit
Removes the fallback method associated with a multi-method.
Just open an issue if you're facing a particular problem. Bonus points if you attach a pull-request ;)
Feel free to ping me on Twitter or
#emacs on Freenode IRC(I'm
kurisumasu) for anything else.