Skip to content

Instantly share code, notes, and snippets.

@friemen
Created October 5, 2014 13:23
Show Gist options
  • Save friemen/9fdc749440aa177d937d to your computer and use it in GitHub Desktop.
Save friemen/9fdc749440aa177d937d to your computer and use it in GitHub Desktop.
Simple decision table implementation
(ns snippets.decision-table)
;; a naive decision table implementation
(defn decision-table
[predicates actions & values]
{:preds predicates
:actions actions
:rows (partition-all (+ (count predicates) (count actions)) values)})
(defn matches?
[x [p v]]
(case v
::any true
true (p x)
false (not (p x))
(p v x)))
(def _ ::any)
(defn exec
[{:keys [preds actions rows]} x]
(->> rows
(mapcat (fn [args]
;; a row consists of arguments
(if (->> args
(map vector preds)
(every? (partial matches? x)))
;; if all predicates return true the actions are applied
(->> args
(drop (count preds))
(map (fn [action v]
(if (not= v ::any) (action v))) actions)))))
(remove nil?)))
;; an example
;; first we define some predicates
(defn in-range?
[[min max] x]
(and (<= (:age x) max)
(<= min (:age x))))
(defn under-18?
[x]
(#{"US"} (:country x)))
(defn license-required?
[x]
(#{"DE" "US"} (:country x)))
(defn license?
[x]
(:driver-license x))
;; here's the table itself
(def dt1 (decision-table
[in-range? under-18? license-required? license?] [identity]
[0 15] _ _ _ "no"
[16 17] true _ true "with adult"
[16 17] false _ _ "no"
[18 150] _ false _ "yes"
[18 150] _ true false "no"
[18 150] _ true true "yes"))
;; now execute the decision tables rules for some data
#_ (exec dt1 {:age 18
:country "DE"
:driver-license "1234"})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment