How to implement a decision matrix/table in Clojure -
there requirement implement decision table below:
membertype amount => discount "guest" > 2000 => 3% "silver" => 5% "silver" > 1000 => 10% "gold" => 15% "gold" > 500 => 20%
i imagine, if implemented in clojure, can define rule table below:
(defrule calc-discount [member-type amount] "guest" (greater-than 2000) => 0.03 "silver" (anything) => 0.05 "silver" (greater-than 1000) => 0.1 "gold" (anything) => 0.15 "gold" (greater-than 500) => 0.2 )
of course, there should better way in writing/defining such rule set. yet key thing think how define "defrule" make happen?
for example, can express business logic rather concisely condp
.
(defn discount [member-type amount] (condp (fn [[type tier] _] (and (= member-type type) (> amount tier))) nil ["guest" 2000] 0.03 ["silver" 1000] 0.10 ["silver" 0] 0.05 ["gold" 500] 0.20 ["gold" 0] 0.15 0.00)) (discount "gold" 600) ;=> 0.2
if looking implement syntax in example, you'll need write macro. rough example:
(defmacro defrule [name fields & clauses] (let [exp (fn [f c] (if (list? c) (list* (first c) f (rest c)) (list `= c f)))] `(defn ~name ~fields (cond ~@(for [clause (partition-all (+ 2 (count fields)) clauses) form [(cons `and (map exp fields clause)) (last clause)]] form))))) (def (constantly true)) (defrule calc-discount [member-type amount] "guest" (> 2000) => 0.03 "silver" (> 1000) => 0.10 "silver" (any) => 0.05 "gold" (> 500) => 0.20 "gold" (any) => 0.15) (calc-discount "silver" 1234) ;=> 0.10
Comments
Post a Comment