このdefun, Clojureの普通の関数定義であるdefnとの違いは, パターンマッチ付きの関数定義ができることです. GitHub中の説明には,
A macro to define clojure functions with parameter pattern matching just like erlang or elixir.とあります.
Clojureのパターンマッチングといえば, core.matchかdefmulti/defmethodのマルチディスパッチですが, 関数の引数に対して, そのままパターンを記述できるので, defn+matchの組み合わせよりもシンプルになります.
.lein/profile.clj (or project.clj)の:pluginsに[defun "0.2.0-RC"]を追加してとりあえず, quicksortもどきを書いてみると,
core.match版
(use '[clojure.core.match :refer [match]]) (defn quicksort1 [ls] (match ls ([] :seq) [] ([x & xs] :seq) (concat (quicksort1 (filter #(< % x) xs)) [x] (quicksort1 (filter #(>= % x) xs)))))と, defun版
(use '[defun :only [defun]]) (defun quicksort2 ([([] :seq)] []) ([([x & xs] :seq)] (concat (quicksort2 (filter #(< % x) xs)) [x] (quicksort2 (filter #(>= % x) xs)))))余分なシンボルが減り, 括弧だけになってすっきりした印象になりました. matchの一旦変数を定義して, それをそのままmatchマクロに渡すという処理がなくなり1行分減り, 変数名が一つ減っています. しかし, 括弧は, 条件一つにつき, 2ペア増えてしまいました. どうやら, この括弧は(大括弧, 小括弧ともに)外せないようです.
(defun sum ([0 m] m) ([n m] (recur (dec n) (+ n m))))こんな感じで, recurが内臓させることも可能なようで, loop-recurの省略にも使えます.
パターンやガードの記述は, core.matchと同じ(というかcore.matchそのもの)なので, core.matchを使う要領で定義できます.