Functional and flexible multimethods for Clojure. Nondestructive multimethod construction, CLOS-style aux methods and method combinations, partial-default dispatch, easy next-method invocation, helpful debugging tools, and more.
I started by trying to add specs to defmethod and defmulti and realized leveraging those to parse args made way more sense than parsing things the hard way. While writing tests and improving the custom Kondo hook I realized we had a few ambiguous parses for defmethod. So this PR introduces the following new rules for dispatch values:
A dispatch value as parsed to defmethod (i.e., not-yet-evaluated) can be ANYTHING other than the following two
things:
an legal aux qualifier for the current method combination, e.g. :after or :around
It makes the parse for
(m/defmethod mf :after \"str\" [_])
ambiguous -- Is this an :after aux method with dispatch value \"str\", or a primary method with dispatch value
:after and a docstring? Since there's no clear way to decide which is which, we're going to have to disallow this.
It's probably a good thing anyway since you're absolutely going to confuse the hell out of people if you use something
like :before or :around as a dispatch value.
A list that can be interpreted as part of a n-arity fn tail i.e. ([args ...] body ...)
I know, theoretically it should be possible to do something dumb like this:
but we are just UNFORTUNATELY going to have to throw up our hands and say we don't support it. The reason is in
the example above it's ambiguous whether this is a :before aux method with dispatch value ([toucan pigeon] i),
or a primary method with dispatch value :before. It's just impossible to tell what you meant. If you really want
to do something wacky like this, let-bind the dispatch value to a symbol or something.
Once I sorted that all out it was relatively straightforward to knock out a few other issues at the same time and add docstring support and custom dispatch value validation support.
Resolves #36 Resolves #46 Resolves #109 Resolves #110 Resolves #113
I started by trying to add specs to
defmethod
anddefmulti
and realized leveraging those to parse args made way more sense than parsing things the hard way. While writing tests and improving the custom Kondo hook I realized we had a few ambiguous parses fordefmethod
. So this PR introduces the following new rules for dispatch values:A dispatch value as parsed to
defmethod
(i.e., not-yet-evaluated) can be ANYTHING other than the following two things:an legal aux qualifier for the current method combination, e.g.
:after
or:around
It makes the parse for
ambiguous -- Is this an
:after
aux method with dispatch value\"str\"
, or a primary method with dispatch value:after
and a docstring? Since there's no clear way to decide which is which, we're going to have to disallow this. It's probably a good thing anyway since you're absolutely going to confuse the hell out of people if you use something like:before
or:around
as a dispatch value.A list that can be interpreted as part of a n-arity fn tail i.e.
([args ...] body ...)
I know, theoretically it should be possible to do something dumb like this:
but we are just UNFORTUNATELY going to have to throw up our hands and say we don't support it. The reason is in the example above it's ambiguous whether this is a
:before
aux method with dispatch value([toucan pigeon] i)
, or a primary method with dispatch value:before
. It's just impossible to tell what you meant. If you really want to do something wacky like this, let-bind the dispatch value to a symbol or something.Once I sorted that all out it was relatively straightforward to knock out a few other issues at the same time and add docstring support and custom dispatch value validation support.
TODO: Update documentation