Implement the concept of "questions" one can ask of an arbitrary entity (ad-hoc components)

Not entirely convinced that this design is the way to go, but am currently without better ideas.
Perhaps each "key" (answerer) could/should provide a dispatch function?
This commit is contained in:
Jeremy Penner 2013-04-30 17:18:50 -04:00
parent 4d0dd8ba8d
commit 5548363a06
2 changed files with 42 additions and 0 deletions

33
src/hottub/question.clj Normal file
View file

@ -0,0 +1,33 @@
(ns hottub.question
(:require [clojure.set :as set]))
(def question-registry (atom {}))
(defn set-questions-for-key [key & questions]
(swap! question-registry
#(reduce (fn [registry question]
(assoc registry question
(if-let [keys (get registry question)]
(conj keys key)
#{key})))
%1 questions)))
(defn keys-for-question
([question]
(or (get @question-registry question) #{}))
([question entity]
(set/intersection (keys-for-question question) (set (keys entity)))))
(defn questions [] (keys @question-registry))
(defmacro defquestion [name [entity & rest-args] & impl]
`(do
(defmulti ~name [entity# ~@rest-args] (first (keys-for-question ~name entity#)))
(defmethod ~name :default [~entity ~@rest-args] ~@impl)))
(set-questions-for-key :foo :bar :x)
(set-questions-for-key :baz :bar :y)
(keys-for-question :bar)
(keys-for-question :bar {})
(keys-for-question :bar {:foo 3})
(questions)

View file

@ -8,3 +8,12 @@
(defn timestamp []
(/ (System/nanoTime) 1000000))
(defn ?assoc
"Same as assoc, b ut skip the assoc if v is nil"
[m & kvs]
(into m
(for [[k v :as e] (partition 2 kvs) :when (not (nil? v))]
(vec e))))