32

I have used erlang in the past and it has some really useful things like pattern matching functions or "function guards". Example from erlang docs is:

fact(N) when N>0 -> 
    N * fact(N-1); 
fact(0) ->      
    1.    

But this could be expanded to a much more complex example where the form of parameter and values inside it are matched.

Is there anything similar in clojure?

mikkom
  • 3,521
  • 5
  • 25
  • 39
  • This is an old question but this project expands core.match to functions and is almost exactly what I was asking years ago https://github.com/killme2008/defun – mikkom Nov 13 '15 at 09:38

4 Answers4

33

There is ongoing work towards doing this with unification in the core.match ( https://github.com/clojure/core.match ) library.

Depending on exactly what you want to do, another common way is to use defmulti/defmethod to dispatch on arbitrary functions. See http://clojuredocs.org/clojure_core/clojure.core/defmulti (at the bottom of that page is the factorial example)

gilesc
  • 1,969
  • 1
  • 14
  • 16
  • 3
    core.match is almost exactly what I'm looking for on the code level, is this part of the core of 1.3 (I don't exactly understand how the clojure packaging works)? With some macros I think it would be possible to extend the syntax to functions (IMHO in erlang the clearest code could be written with pattern matching functions with guards) – mikkom Dec 22 '11 at 08:04
  • It requires 1.3 but is not part of 1.3 by default. If you are using Leiningen (https://github.com/technomancy/leiningen) -- and you should be -- then you add a line '[org.clojure/core.match "0.2.0-alpha8"]' to your project.clj's dependencies, then run lein deps. And yes as you can see at the bottom of their github page, the devs plan to apply core.match to functions (predicate dispatch) soon. – gilesc Dec 22 '11 at 20:33
  • If anyone else runs into trouble pattern matching function arguments, use `vec`: http://nickknowlson.com/blog/2013/02/17/using-core-match-with-function-arguments/ – Nick Knowlson Feb 17 '13 at 21:28
19

I want to introduce defun, it's a macro to define functions with pattern matching just like erlang,it's based on core.match. The above fact function can be wrote into:

(use 'defun)
(defun fact
  ([0] 1)
  ([(n :guard #(> % 0))] 
    (* n (fact (dec n)))))

Another example, an accumulator from zero to positive number n:

(defun accum
  ([0 ret] ret)
  ([n ret] (recur (dec n) (+ n ret)))
  ([n] (recur n 0)))

More information please see https://github.com/killme2008/defun

killme2008
  • 207
  • 2
  • 4
9

core.match is a full-featured and extensible pattern matching library for Clojure. With a little macro magic and you can probably get a pretty close approximation to what you're looking for.

Dave Ray
  • 39,616
  • 7
  • 83
  • 82
3

Also, if you want to take apart only simple structures like vectors and maps (any thing that is sequence or map, e.g. record, in fact), you could also use destructuring bind. This is the weaker form of pattern matching, but still is very useful. Despite it is described in let section there, it can be used in many contexts, including function definitions.

Vladimir Matveev
  • 120,085
  • 34
  • 287
  • 296