2011-12-21 84 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