Clojure マルチメソッド

(defmulti area :Shape)
(defn rect[wd ht] {:Shape :Rect :wd wd :ht ht})
(defn circle[radius] {:Shape :Circle :radius radius})
(defn in-fun-shape[fun a b] {:Shape :InFunction :fun fun :a a :b b})

(defmethod area :Circle [c]
  (* (. Math PI) (* (:radius c) (:radius c))))
(defmethod area :Rect [r]
  (* (:wd r) (:ht r)))
; y=f(x)と区間 a-b に囲まれた図形の面積
(defmethod area :InFunction [in-fun]
  (let [a   (:a in-fun)
        b   (:b in-fun)
        fun (:fun in-fun)
        dx (/ (- b a) 1000000.0)]
    (reduce + (map #(* (fun %) dx) (range a b dx))) ))

(defmethod area :default [x] :oops)

(def r (rect 4 13))
(def c (circle 12))
(def f (in-fun-shape (fn[x] (* x x)) 0 1))

(println (map area [r c f {}]))

;;; #=>(52 452.3893421169302 0.33333283333399866 :oops)

OOのポリモーフィズムっぽい感じがした。Scalaの パターンマッチングのようなことが出来るかは、よくわからなかった。

http://clojure.org/multimethods