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

ответ

27

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

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

+3

CoreMatch почти точно, что я ищу на уровне кода, является ли эта часть ядро 1.3 (я не совсем понимаю, как c лихорадочные упаковочные работы)? С некоторыми макросами я думаю, что было бы возможно расширить синтаксис до функций (IMHO в erlang, самый четкий код может быть написан с функциями сопоставления шаблонов с защитой) – mikkom

+0

Он требует 1.3, но по умолчанию не является частью 1.3. Если вы используете Leiningen (https://github.com/technomancy/leiningen) - и вы должны быть - тогда вы добавляете строку '[org.clojure/core.match "0.2.0-alpha8"]' в ваших зависимостей project.clj, а затем запускайте отладки. И да, как вы можете видеть внизу своей страницы github, разработчики планируют в ближайшее время применить функции core.match к функциям (отправку предикатов). – gilesc

+0

Если кто-то еще сталкивается с аргументами функции соответствия шаблону проблемы, используйте 'vec': http://nickknowlson.com/blog/2013/02/17/using-core-match-with-function-arguments/ –

9

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

3

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

+2

Разрушение - это довольно бит слишком ограничен для реального соответствия шаблону. – mikkom

12

Я хочу ввести defun, это макрос, чтобы определять функции с шаблоном, аналогичным примеру erlang, на основе core.match. Выше функция факта может быть начертана в:

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

Другого пример, аккумулятор от нуля до положительного числа п:

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

Более подробной информации см https://github.com/killme2008/defun

+1

Это красиво! Удачи в проекте. Я уверен, что это поможет многим людям, поскольку функции сопоставления шаблонов являются одним из самых недооцененных в программировании. – mikkom

+0

@ killme2008, мне очень нравится ваша работа с defun. Каковы преимущества defun над core.match? –

Смежные вопросы