From 27fa774f7bb2ce1ed4167c8718b501b39ee23d3d Mon Sep 17 00:00:00 2001 From: Jeremy Penner Date: Sat, 4 May 2013 00:19:46 -0400 Subject: [PATCH] rework question API to use arbitrary functions for dispatch --- src/hottub/question.clj | 55 ++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/src/hottub/question.clj b/src/hottub/question.clj index 791d539..971e799 100644 --- a/src/hottub/question.clj +++ b/src/hottub/question.clj @@ -1,33 +1,38 @@ (ns hottub.question (:require [clojure.set :as set])) +(defstruct responder :fnrespond :fncanrespond) + (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)) +(defn clear-responder + [id] + (doseq [question (questions)] + (clear-responder question id)) + [question id] + (swap! question-registry + #(if-let [responders (get % question)] + (assoc % question (disassoc responders id)) + %))) -(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))) +(defn set-responder [id question fnrespond fncanrespond] + (let [responder (struct responder fnrespond fncanrespond)] + (swap! question-registry assoc-in [question id] responder))) -(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) +(defn responders + [question] + (vals (get @question-registry question)) + [question entity] + (filter #((:fncanrespond %) question entity) (responders question))) + +(defn ask-all [question entity] + (map #((:fnrespond %) question entity) (responders question entity))) + +(defn ask + [question entity] (ask question entity nil) + [question entity default] + (let [results (ask-all question entity)] + (if (seq results) + (first results) + default)))