Функции сопоставления с образцом в Clojure? - PullRequest
28 голосов
/ 22 декабря 2011

В прошлом я использовал erlang, и у него есть некоторые действительно полезные вещи, такие как функции сопоставления с образцом или «защита функций». Пример из документации erlang:

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

Но это может быть расширено до гораздо более сложного примера, где форма параметра и значения внутри него совпадают.

Есть ли что-нибудь похожее в clojure?

Ответы [ 4 ]

30 голосов
/ 22 декабря 2011

В настоящее время ведется работа по унификации в библиотеке core.match (https://github.com/clojure/core.match).

В зависимости от того, что именно вы хотите сделать, другим распространенным способом является использование defmulti / defmethod для отправки произвольных функций.См. http://clojuredocs.org/clojure_core/clojure.core/defmulti (в нижней части этой страницы приведен пример фактора)

14 голосов
/ 19 сентября 2014

Я хочу представить 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

9 голосов
/ 22 декабря 2011

core.match - это полнофункциональная и расширяемая библиотека сопоставления с образцом для Clojure. С небольшим количеством магии макроса, и вы, вероятно, получите довольно близкое приближение к тому, что вы ищете.

3 голосов
/ 22 декабря 2011

Кроме того, если вы хотите разбирать только простые структуры, такие как векторы и карты (любая вещь, которая является последовательностью или картой, например, записью, на самом деле), вы также можете использовать деструктурирующее связывание .Это более слабая форма сопоставления с образцом, но все же она очень полезна.Несмотря на то, что он описан в разделе let, его можно использовать во многих контекстах, включая определения функций.

...