Skip to content
Branch: master
Go to file
Code

Latest commit

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 

README.md

Intentions

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.

Installation

Add the following dependency to your project:

[intentions "0.2.1"]

Usage

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

License

Copyright © 2016 James Reeves

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

About

Multimethods that combine rather than override inherited behavior

Resources

You can’t perform that action at this time.