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

Popular posts from this blog

apache - Remove .php and add trailing slash in url using htaccess not loading css -

javascript - jQuery show full size image on click -