sema-docs 1.23.0

Canonical structured documentation for Sema builtins/special forms; powers LSP hover/completion and REPL apropos
Documentation
---
name: "defmulti"
module: "special-forms"
syntax: "(defmulti name dispatch-fn)"
---

Define a multimethod — a function whose implementation is selected at runtime by applying a dispatch function to the arguments. The `name` must be a symbol. The `dispatch-fn` is a regular function that receives the same arguments as the multimethod and returns a dispatch value. Methods are registered separately with `defmethod`, associating a dispatch value with a handler function.

Multimethods are open for extension: new methods can be added after the multimethod is defined, even from other modules. If no method matches the dispatch value and no `:default` method is registered, an error is raised. Dispatch values can be keywords, strings, numbers, lists, or any comparable value.

```sema
(defmulti area (fn (shape) (get shape :type)))
(defmethod area :circle (fn (s) (* 3.14159 (expt (get s :radius) 2))))
(defmethod area :rect   (fn (s) (* (get s :width) (get s :height))))

(area {:type :circle :radius 5})   ; => 78.53975
(area {:type :rect :width 3 :height 4})  ; => 12
```

Dispatch on runtime type:

```sema
(defmulti describe (fn (x) (type x)))
(defmethod describe :int    (fn (x) "integer"))
(defmethod describe :string (fn (x) "text"))
(defmethod describe :list   (fn (x) "list"))

(list (describe 42) (describe "hi") (describe '(1 2)))
;; => ("integer" "text" "list")
```

Multi-argument dispatch:

```sema
(defmulti combine (fn (a b) (list (type a) (type b))))
(defmethod combine '(:int :int)       (fn (a b) (+ a b)))
(defmethod combine '(:string :string) (fn (a b) (string-append a b)))

(combine 1 2)      ; => 3
(combine "a" "b")  ; => "ab"
```