hey all, I'm following along the Learn Datalog Today tutorials, and ran into some really unexpected behavior on chapter 6 where they use transformation functions in a join query. Here's a shrunken down version of the scenario:
(d/q '[:find ?n1 ?n2
:where
[?p1 :name ?n1]
[?p2 :name ?n2]
[?p1 :born ?b1]
[?p2 :born ?b2]
[(clojure.core/first ?b1) ?day]
[(clojure.core/first ?b2) ?day]
[(clojure.core/second ?b1) ?month]
[(clojure.core/second ?b2) ?month]
[(< ?p1 ?p2)]]
(d/db-with (d/empty-db)
[{:name "A" :born [1 1 1980]}
{:name "B" :born [1 1 1981]}
{:name "C" :born [1 2 1982]}
{:name "D" :born [2 2 1983]}
{:name "E" :born [5 6 1984]}]))
;; => #{["A" "C"] ["B" "C"] ["A" "B"]}
I'd expect the only match to be ["A" "B"] , can anyone help explain why AC and BC are also being returned? Note that it does not match the CD pair (which share a month) so the semantics aren't even consistent with the clauses being combined disjunctivelyHere's a link to the original page (exercise 3, birthday paradox) https://learn-some.com/chapter/6 - the reference solution is logically the same (but using interop syntax on the insts which Datascript doesn't seem to support)
Even stranger, if I reorder the clauses so that ?month comes first, it produces a different 'wrong' result:
(d/q '[:find ?n1 ?n2
:where
[?p1 :name ?n1]
[?p2 :name ?n2]
[?p1 :born ?b1]
[?p2 :born ?b2]
[(clojure.core/second ?b1) ?month]
[(clojure.core/second ?b2) ?month]
[(clojure.core/first ?b1) ?day]
[(clojure.core/first ?b2) ?day]
[(< ?p1 ?p2)]]
db)
;; => #{["C" "D"] ["A" "B"]}This is in Datascript, right? Might be a bug. What’s Datomic’s output?
I don't have a copy of Datomic to test with, but it should output [A B] according to the tutorial
Maybe we don’t do unification on function call assignment, I don’t remember. Open an issue
oh funny enough it works if you put it in a rule
(d/q '[:find ?n1, ?n2
:in $ %
:where
[?p1 :name ?n1]
[?p2 :name ?n2]
(birthday ?p1 ?day ?month)
(birthday ?p2 ?day ?month)
[(< ?p1 ?p2)]]
db
'[[(birthday ?p ?d ?m)
[?p :born ?b]
[(clojure.core/first ?b) ?d]
[(clojure.core/second ?b) ?m]]])
;; => #{["A" "B"]}Yeah, out parameters on rules are implemented differently