Fork me on GitHub

I’m trying to figure out if there is a way to accumulate some joined data. I haven’t been able to come up with a single rule which will fire with my desired output. In the following example, I am trying to answer the question, what is the sum of quantities for each name:

(defrecord A [id name])
(defrecord B [id quantity])

(defrule merge-things
  (println ?name ?total-quanity))

(-> (mk-session)
    (insert (->A 1 "car"))
    (insert (->A 2 "truck"))
    (insert (->A 3 "car"))
    (insert (->B 1 2))
    (insert (->B 2 3))
    (insert (->B 3 5))
I am trying to have that rule print out:
car 7
truck 3


I haven’t been able to come up with a ??? for that rule which works.


Well, duckie to the rescue. While typing this up, I found one way I hadn’t tried. So now my question is, are there any problems with the following rule definition? (memory,performance,other,…) It is different that other rules I’ve used. Not sure if using the accumulator and re-creating the set of ids — (set (map :id ?a)) — in the rule expression would cause any unexpected problems.

(defrule merge-things
  [?a <- (acc/all) :from [A (= ?name name)]]
  [?total-quantity <- (acc/sum :quantity) :from [B (get (set (map :id ?a)) id)]]
  (println ?name ?total-quantity))