palisades.lakes.multimethods.core

Faster multimethod method lookup.

defmethod

macro

added in faster-multimethods 0.0.0

(defmethod multifn v & fn-tail)

Creates and installs a new method for multifn associated with dispatch value v.

  • multifn: an instance of palisades.lakes.multimethods.java.MultiFn, created with palisades.lakes.multimethods.core/defmulti.

  • v: satisfies (legal-dispatch-value? multifn v).

  • fn-tail: one or more of arglist plus function body, which are passed to fn to generate the method function. Note that signatures only support single arity method functions.

Throws an exception if v is not a legal dispatch value for multifn.

Warning: mutates multifn.

Note: unlike defmulti, re-evaluating defmethod will replace any existing method for v.

Note: defmethod can only be used with multimethods defined with palisades.lakes.multimethods.core/defmulti.

defmulti

macro

added in faster-multimethods 0.0.0

(defmulti mm-name docstring? attr-map? dispatch-fn & options)

Creates a new multimethod (an instance of palisades.lakes.multimethods.java.MultiFn) named mm-name that uses dispatch-fn to generate dispatch values.

  • mm-name: a namespace qualified Symbol. The MultFn will be the value of the Var with that name.

  • docstring? (optional): documentation string used as the :doc metadata on #'mm-name.

  • attr-map? (optional): more metadata for #'mm-name.

  • dispatch-fn an instance of clojure.lang.IFn that returns legal dispatch values when applied to (supported) arguments passed to the MultiFn. There is no check that the dispatch-fn returns legal values. You may use legal-dispatch-value? in the dispatch-fn to validate the returned value, perhaps only during debugging if performance is critical.

  • options (optional): are key-value pairs and may be one of:

    • :hierarchy: false, nil, or a Var whose value is a hierarchy. Used for method lookup when the dispatch values are or contain namespace-qualified instances of Named.

      See multimethods and hierarchies for information on how to create and modify hierarchies.

      If the :hierarchy is not supplied, it defaults to #'clojure.core/global-hierarchy.

      If :hierarchy is supplied and its value is nil or false, then only Class and Signature dispatch values are permitted, and method lookup is optimized for that case.

      Otherwise the value of the :hierarchy option must be a Var (i.e. via the Var-quote dispatch macro #’ or the var special form) holding a hashmap created with clojure.core/make-hierarchy.

      Warning: Multimethods that use hierarchies depend on mutable shared state. It is possible for someone else to modify the shared hierarchy in a way that breaks method lookup.

      Warning: the Clojure hierarchy functions behave differently for the default #'clojure.core/global-hierarchy versus a custom local hierarchy. Updates to the global hierarchy call alter-var-root on #'clojure.core/global-hierarchy, mutating shared state. Updates to a custom hierarchy return a new hashmap; it’s left to the caller to rebind any Var which might be pointing to the original hierarchy. If you use a local hierarchy, and modify it after the multimethod is created, it will have no effect unless you explicitly rebind the Var that was passed to defmulti. This is an easy mistake to make, and not so easy to see what’s wrong.

      Note: like the Clojure implementation, there is no way to determine what hierarchy is used by an existing multimethod, which might be useful if you wanted to ensure a new multimethod had the same inheritance behavior as an existing one. This may change in a future release.

    • :default: The default dispatch value, defaults to :default. Not supported, and an exception is thrown, when :hierarchy false or :hierarchy nil and the value of :default is not false or nil.

Warning: If #'mm-name is already defined and its value is a MultiFn, defmulti silently does nothing. This is the Clojure 1.8.0 defmulti behavior. This may change in a future release.
(This seems to me like bad answer to the problem of accidentally re-evaluating a given defmulti and wiping out all the methods. I think a better design would make MultiFn effectively immutable. defmulti, defmethod, etc., would return new instances which are updates of the existing instance, and call alter-var-root to update the value of #'mm-name. This, I believe, is what defn does.)

dominates<

added in faster-multimethods 0.0.8

(dominates< multifn x y)

Transitive extension of isa< with pairs created by calls to prefer-method.
(dominates< multifn x y) is eqiuvalent to (and (dominates<= multifn x y) (not= x y)).

Throws an exception if x and y are not legal dispatch values for multifn.

Not used in method lookup, which is implemented in Java, but may be useful for debugging.

dominates<=

added in faster-multimethods 0.0.8

(dominates<= multifn x y)

Transitive extension of isa<= with pairs created by calls to prefer-method.
(dominates<= multifn x y) is eqiuvalent to (or (dominates< multifn x y) (= x y)).

Throws an exception if x and y are not legal dispatch values for multifn.

Not used in method lookup, which is implemented in Java, but may be useful for debugging.

get-method

added in faster-multimethods 0.0.0

(get-method multifn v)

Given a multimethod multifn and a dispatch value v, returns the defined method function that would be applied to any arglist that resulted in the dispatch value v. If there are no methods that are applicable to v, returns nil.

Note: get-method can only be used with multimethods defined with palisades.lakes.multimethods.core/defmulti.

Warning: Does NOT throw an exception if v is an illegal dispatch value for multifn; returns nil in that case.

isa<

added in faster-multimethods 0.0.8

(isa< multifn x y)

Extension of clojure.core/isa?, for a particular multimethod, to all legal dispatch values.
(isa< multifn x y) is eqiuvalent to (and (isa<= multifn x y) (not= x y)).
isa< implies dominates<.

Throws an exception if x and y are not legal dispatch values for multifn.

Not used in method lookup, which is implemented in Java, but may be useful for debugging.

isa<=

added in faster-multimethods 0.0.8

(isa<= multifn x y)

Extension of clojure.core/isa?, for a particular multimethod, to all legal dispatch values.
(isa<= multifn x y) is eqiuvalent to (or (isa< multifn x y) (= x y))
. isa<= implies dominates<=.

Throws an exception if x and y are not legal dispatch values for multifn.

Not used in method lookup, which is implemented in Java, but may be useful for debugging.

methods

added in faster-multimethods 0.0.0

(methods multifn)

Given a multimethod, returns a map of dispatch values -> method functions.

Note: methods can only be used with multimethods defined with palisades.lakes.multimethods.core/defmulti.

prefer-method

added in faster-multimethods 0.0.0

(prefer-method multifn x y)

Causes the multimethod to prefer matches of x over y when there is a conflict.

Throws an exception if x and y are not legal dispatch values for multifn.

Note: prefer-method can only be used with multimethods defined with palisades.lakes.multimethods.core/defmulti.

Warning: mutates multifn.

prefers

added in faster-multimethods 0.0.0

(prefers multifn)

Given a multimethod, returns a map of more preferred dispatch value -> set of less preferred dispatch values.

Note: prefers can only be used with multimethods defined with palisades.lakes.multimethods.core/defmulti.

remove-all-methods

added in faster-multimethods 0.0.0

(remove-all-methods multifn)

Removes all of the methods of multimethod.

Note: remove-all-methods can only be used with multimethods defined with palisades.lakes.multimethods.core/defmulti.

Warning: despite the name, this actually removes all the preferences, in addition to the methods, and clears the cache.

Warning: mutates multifn.

remove-method

added in faster-multimethods 0.0.0

(remove-method multifn v)

Removes the method of multimethod associated with v. Does nothing if no method is defined for v.

Throws an exception if v is not legal dispatch value for multifn.

Note: remove-method can only be used with multimethods defined with palisades.lakes.multimethods.core/defmulti.

Warning: mutates multifn.

signature

added in faster-multimethods 0.0.9

(signature)(signature x0)(signature x0 x1)(signature x0 x1 x2)(signature x0 x1 x2 & xs)

The standard dispatch function for the :hierarchy false case. Returns the Class of the argument for arity 1, and an appropriate implementation of Signature for other arities, calling (.getClass xi) as needed.

Warning: signature can only be used as a dispatch function with multimethods defined with palisades.lakes.multimethods.core/defmulti.

signature?

added in faster-multimethods 0.0.8

(signature? v)

Is v a signature (ie, an instance of palisades.lakes.multimethods.java.Signature)?

to-signature

added in faster-multimethods 0.0.9

(to-signature)(to-signature c0)(to-signature c0 c1)(to-signature c0 c1 c2)(to-signature c0 c1 c2 & cs)

Return an appropriate instance of Signature for the Class valued arguments (in the arity 1 case, it just returns the Class itself).

Warning: to-signature can only be used to generate dispatch values for multimethods defined with palisades.lakes.multimethods.core/defmulti.