2011-12-21 63 views
25

我在过去使用过erlang,它有一些非常有用的功能,比如模式匹配功能或“功能卫士”。从二郎文档的例子是:Clojure中的模式匹配功能?

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

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

clojure有类似的东西吗?

+0

这是一个老问题,但这个项目扩展core.match功能,几乎正是我多年前所要求的https://github.com/killme2008/defun – mikkom 2015-11-13 09:38:39

回答

27

存在向在core.match(https://github.com/clojure/core.match)库统一做这个正在进行的工作。

取决于你想要做什么,另一种常见的方法是使用defmulti/defmethod派遣的任意函数。请参阅http://clojuredocs.org/clojure_core/clojure.core/defmulti(该页面的底部是因子示例)

+3

core.match几乎正是我所期待的代码级别,是这部分1.3的核心(我不完全明白如何c lojure包装工程)?对于一些宏,我认为可以将语法扩展到函数(在erlang中的恕我直言,最清晰的代码可以用带有保护的模式匹配函数编写) – mikkom 2011-12-22 08:04:21

+0

它需要1.3,但默认情况下不是1.3的一部分。如果你正在使用Leiningen(https://github.com/technomancy/leiningen) - 你应该 - 然后你添加一行'[org.clojure/core.match'0.2.0-alpha8“]'到你的project.clj的依赖关系,然后运行lein deps。是的,正如你可以在他们的github页面的底部看到的,开发人员计划很快将core.match应用于函数(谓词调度)。 – gilesc 2011-12-22 20:33:12

+0

如果其他人遇到模式匹配函数参数的麻烦,请使用'vec':http://nickknowlson.com/blog/2013/02/17/using-core-match-with-function-arguments/ – 2013-02-17 21:28:51

9

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

3

另外,如果您只想拆分简单结构(如矢量和地图)(实际上是序列或地图,例如记录),那么您也可以使用destructuring bind。这是模式匹配的较弱形式,但仍然非常有用。尽管它在let部分中有描述,但它可用于许多情况下,包括函数定义。

+2

解构是一个相当对于实际的模式匹配来说太有限了。 – mikkom 2011-12-22 08:02:16

12

我想介绍defun,它的定义与模式匹配就像二郎神功能的宏,它是基于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

+1

这很美!项目的好运我相信它会帮助很多人作为模式匹配函数是编程中最被低估的事情之一。 – mikkom 2014-09-26 11:09:38

+0

@ killme2008,我真的很喜欢你与defun的合作。 defun比core.match有什么优势? – 2016-08-20 18:57:04