clojureclojurescriptdatomicdatalogdatascript

Why does this datalog query aggregate?


From https://github.com/tonsky/datascript

(->
 (d/q '[:find ?color (max ?amount ?x) (min ?amount ?x)
        :in   [[?color ?x]] ?amount]
      [[:red 10]  [:red 20] [:red 30] [:red 40] [:red 50]
       [:blue 7] [:blue 8]]
      4)
 pr-str
 js/console.log)
;;; ([:red [20 30 40 50] [10 20 30 40]] [:blue [7 8] [7 8]]) 

(->
 (d/q '[:find ?color (max ?amount ?x) (min ?amount ?x)
        :in   [[?color ?x]] ?amount]
      [[:red 10]  [:red 20] [:red 30] [:red 40] [:red 50]
       [:blue 7] [:blue 8]]
      3)
 pr-str
 js/console.log)
;;; ([:red [30 40 50] [10 20 30]] [:blue [7 8] [7 8]]) 

(->
 (d/q '[:find ?color (max ?amount ?x) (min ?amount ?x)
        :in   [[?color ?x]] ?amount]
      [[:red 10]  [:red 20] [:red 30] [:red 40] [:red 50]
       [:blue 7] [:blue 8]]
      2)
 pr-str
 js/console.log)
;;; ([:red [40 50] [10 20]] [:blue [7 8] [7 8]]) 

So, this isn't a question about what it is doing, this is a question of how (or at least why) it is doing it. max and min are functions that return the maximum or minimum of their following integers, respectively. How is ?amount getting factored into limiting the aggregation count? Why are these things aggregating anyway? How is the code being run such that it aggregates. I really don't see how this code is flowing to generate the results it does.


Solution

  • max and min are overloaded in datomic queries.

    The unary (min ?x) and (max ?x) functions aggreate to return a single number.

    The binary (min ?n ?x) and (max ?n ?x) functions aggreate to return a collection of items limited in length by ?n.