Skip to content
Branch: master
Go to file

Latest commit


Failed to load latest commit information.
Latest commit message
Commit time


Build Status

Intentions are a tool for runtime polymorphism in Clojure and ClojureScript. They behave much same as multimethods, with one key exception: where multimethods override inherited behavior, intentions combine it.


Add the following dependency to your project:

[intentions "0.2.1"]


An intention is created with defintent:

(defintent valid?
  :dispatch :type
  :combine #(and %1 %2))

An intention needs both a dispatch function, and a combine function. The combine function combines two return values into one. In this case, we perform a logical AND on the values.

Once an intention is stated, behavior can be added using conducts. These are analogous to methods:

(derive ::square ::quad)

(defconduct valid? ::quad [shape]
  (= (count (:sides shape)) 4))

(defconduct valid? ::square [shape]
  (apply = (:sides shape))

Unlike methods, conducts with derived dispatch values combine the functionality of their parents. Because ::square derives from ::quad, both conducts are applied, then combined using and:

(valid? {:type ::square, :sides [2 2 2 2]})
-> true

(valid? {:type ::square, :sides [2 2 2]})
-> false

Conducts are combined in a fixed order down the inheritance tree, with parents evaluated before children. So in the above case, the conduct for ::quad is evaluated before ::square. This ordering is particularly useful when using a combining function like merge.

When the inheritance order is ambiguous (such as in the case of a diamond dependency), dependencies are converted to strings and ordered alphanumerically, so as to always provide a consistent ordering. This can be overridden by using the prefer-conduct function.

For example:

;; Diamond dependency graph
(derive ::b ::a)
(derive ::c ::a)
(derive ::d ::b)
(derive ::d ::a)

(defintent order-example
  :dispatch identity
  :combine  concat)

(defconduct ::b [_] '(b))
(defconduct ::c [_] '(c))

If we were to dispatch on ::d, the order in which to apply ::b and ::c is ambiguous, so we default to alphanumeric ordering:

(order-example ::d)
-> (b c)

To explicit specify an ordering, use prefer-conduct:

(prefer-conduct order-example ::c ::b)
(order-example ::d)
-> (c b)

Further Documentation


Copyright © 2016 James Reeves

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.


Multimethods that combine rather than override inherited behavior


You can’t perform that action at this time.