Provides `defpatterned` to define functions that pattern-match on their args
Available via clojars Leiningen: [patterned "0.2.0"]
Provides defpatterned
to define Clojure functions in a
somewhat Haskell-like way.
Here is a simple example showing an implementation of that has a single-argument main interface and a two-step recursive function that uses a collecting parameter.
(defpatterned factorial
[n] (factorial 1 n)
[so-far 0] so-far
[so-far n] (factorial (* n so-far) (dec n)))
Matches are made recursively when the pattern contains subvectors:
(defpatterned deep
[:a [1]] "a simple match"
[s [1 [1 [n]]]] (str "a match of " s " and " n))
user=> (deep :a [1])
"a simple match"
user=> (deep :b [1 [1 [3]]])
"a match of :b and 3"
Rest arguments are supported. Here's a typical recursive implementation of a sequence function:
(defpatterned count-sequence
[[]] 0
[[head & tail]] (inc (count-sequence tail)))
user=> (count-sequence [10 9 8 7 6 5 4 3 2 1])
10
A list containing :when
may be used to match any argument that passes
a predicate. An optional :bind
argument names a symbol that will be
bound on the right-hand side:
(defpatterned classify-number
[(:when odd? :bind n)] (str "odd number " n)
[(:when even?)] (str "some even number"))
user=> (classify-number 5)
"odd number 5"
user=> (classify-number 6)
"some even number"
A list containing :in
will match any one of a number of literals. :bind
can be used to find out which value matched. Here is a factorial that uses both :in
and :when
:
(defpatterned factorial
[(:when (partial > 0) :bind n)] (oops! "Bad number" :n n)
[(:in [0 1])] 1
[n] (* n (factorial (dec n))))
The patterned
macro is the pattern-matching equivalent of
fn
:
( (patterned
[1] "one"
[n] "other")
8888)
The letpatterned
macro is the pattern-matching equivalent of letfn
:
(letpatterned
[(f1 [0] 0 [n] (f2 (dec n)))
(f2 [0] 1 [n] (f1 (dec n)))]
(f2 88))
This library is in support of Functional Programming for the Object-Oriented Programmer. Feel free to use it for other things. Please note:
This is not based on clojure.core.match
because I had
trouble getting that working.
Speed was not a concern.
Right now, all you can do is write functions. There's no support for matching expressions inside a function.