Clojure中的模式匹配函数?

时间:2011-12-21 22:02:29

标签: clojure design-patterns matching

我过去曾使用过erlang,它有一些非常实用的功能,比如模式匹配功能或"功能保护"。来自erlang docs的示例是:

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

但是这可以扩展到一个更复杂的例子,其中的参数和值的形式是匹配的。

clojure中有类似的东西吗?

4 个答案:

答案 0 :(得分:30)

目前正在努力通过core.match(https://github.com/clojure/core.match)库中的统一来实现这一目标。

根据您想要做什么,另一种常见的方法是使用defmulti / defmethod来调度任意函数。请参阅http://clojuredocs.org/clojure_core/clojure.core/defmulti(该页面底部是因子示例)

答案 1 :(得分:14)

我想介绍defun,它是一个宏来定义模式匹配的函数,就像erlang一样,它基于core.match。上述事实函数可写入:

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

另一个例子,累加器从零到正数n:

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

更多信息,请参阅https://github.com/killme2008/defun

答案 2 :(得分:9)

core.match是Clojure的全功能和可扩展模式匹配库。有了一点宏观魔法,你可能会非常接近你正在寻找的东西。

答案 3 :(得分:3)

另外,如果你只想拆分像矢量和地图这样的简单结构(任何序列或地图的东西,例如记录,实际上),你也可以使用destructuring bind。这是较弱的模式匹配形式,但仍然非常有用。尽管在let部分对其进行了描述,但它可以在许多上下文中使用,包括函数定义。