Function Dispatch

Function dispatch, loosely speaking, allows a function to be calculated by different code based on the manner in which it is called. Of course, this description also applies to conditional evaluation, but function dispatch tends to be more declarative, modular, etc.

Clojure supports various forms of function dispatch, based on argument arity, type, value, etc.

Motivation

Conditional evaluation can achieve many of the same results as function dispatch. For example, the cond macro can be used to evaluate different code, based on arbitrary criteria.

However, this approach has some significant drawbacks:

  • The code resides in a single function,
    complecting selection and evaluation.

  • The function must be edited whenever a case
    needs to be added, modified, or removed.

  • The approach is imperative, rather than declarative.

Consequently, the approaches described below are generally preferable.

Arities

Clojure functions can be defined in multiple sections, each of which handles a different arity (ie, number of arguments), eg:

(defn foo
  ([] ... )
  ([x] ... )
  ([x y] ... )
  ([x y & more] ... ) )

Interfaces

Java's interfaces support statically-defined single dispatch, based on the class of the receiving object. See the Java, etc. page and the Protocols section (below) for more information.

Multimethods

Clojure's multimethods support multiple dispatch, based on arbitrary criteria:

A Clojure multimethod is a combination of a dispatching function and one or more methods. When a multimethod is defined, using defmulti, a dispatching function must be supplied. This function will be applied to the arguments to the multimethod in order to produce a dispatching value. The multimethod will then try to find the method associated with the dispatching value or a value from which the dispatching value is derived. ...

-- http://clojure.org/multimethods

Although multimethods can be (and historically, were) used to dispatch based the type of the first argument (eg, the type of the receiving Java object), protocols now provide a more declarative, extensible, and efficient solution for this use case. However, multimethods are still useful, because they can handle many other types of dispatch.

Protocols

Clojure's protocols support single dispatch, based on the type (eg, String) of a function's first argument. So, like Java's interfaces, they handle the common case of dispatching on an object's type. However, protocols also allow dynamic creation and extension and sidestep the requirement for class hierarchies, etc.


This wiki page is maintained by Rich Morin, an independent consultant specializing in software design, development, and documentation. Please feel free to email comments, inquiries, suggestions, etc!

Topic revision: r3 - 04 Mar 2013, RichMorin
This site is powered by Foswiki Copyright © by the contributing authors. All material on this wiki is the property of the contributing authors.
Foswiki version v2.1.6, Release Foswiki-2.1.6, Plugin API version 2.4
Ideas, requests, problems regarding CFCL Wiki? Send us email