I'm rather new to datahike/datomic/datascript, and I'm solo here, so my learning process consists mostly of reading the datomic docs and searching open source code on github/SO Sometimes I come across code that doesn't seem to work in datahike, and I don't know why. Here's an example:
(def rules
'[[(owns? ?uid ?e)
[?e :auth/owner ?user]
[?user :account/id ?uid]]
[(owns? ?uid ?e)
[?e ?ref-attr ?r]
(owns? ?uid ?r)]])
;; Does not work
;; Unknown predicate 'owns? in [(owns? ?account-id ?e)]
;; {:error :query/where, :form [(owns? ?account-id ?e)], :var owns?}
(d/q '[:find [?e ...]
:in $ ?account-id %
:where
[?e :form/id ?v]
[(owns? ?account-id ?e)]]
@conn account-id rules)
;; Works
(d/q '[:find [?e ...]
:in $ ?account-id %
:where
[?e :form/id ?v]
(owns? ?account-id ?e)] ;; <--- change here
@conn account-id rules)
Why does removing the (owns?...
from the vector make it work?
I got the broken version https://www.slideshare.net/lucascavalcantisantos/exploring-four-datomic-superpowers (slide 56). Is this a datahike/datomic difference? Has syntax changed since 2014? Did I miss something?Hey @ramblurr, let me check this myself and get back to you. So the query works with Datomic right?
I only ran the code above with datahike. I pulled the code from the linked presentation where nubank was using datomic. Presumably it works in datomic, but I can't test it.
I suppose it's possible they typoed in their slides, but I've seen other examples of [(rule ...)]
in the wild
Ok, where does the owns?
function come from?
You can use some built-in functions inside the rules that are defined https://github.com/replikativ/datahike/blob/development/src/datahike/query.cljc#L234. Alternatively you may use Java methods like .matches
in Regexes as resolved in https://github.com/replikativ/datahike/blob/development/src/datahike/query.cljc#L572.
owns?
is not a function, it is a rule (see https://docs.datomic.com/on-prem/query/query.html#rules)
(def rules
'[[(owns? ?uid ?e)
[?e :auth/owner ?user]
[?user :account/id ?uid]]
That is the "declaration" of the (owns?...)
rule.Thanks, now I understand your problem. Yes Datahike’s rules are used only without the vector, that’s how it resolves it. Inside the clause it would be treated as a predicate. In Datomic it is the same as shown in “Day of Datomic” https://github.com/Datomic/day-of-datomic/blob/master/tutorial/time-rules.clj#L50.
@ramblurr I think it's just a typo in the slides. Both Datomic and DataScript differentiate rules (rule ...)
from predicates [(pred? ...)]
by that wrapped vector.
See how the definition of a rule differs from the usage in a where clause in these examples: https://docs.datomic.com/cloud/query/query-data-reference.html#rules
And you can even see it in the DataScript tests here: https://github.com/tonsky/datascript/blob/master/test/datascript/test/query_rules.cljc#L25-L26
Ok brilliant, that settles that. Thanks folks. One challenging thing with datomic/datahike/datascript is the web isn't full of examples and articles. Thanks for those two links, i hadn't found that datomic docs page. It shows the syntax clearly.
@ramblurr if you haven't seen it, http://www.learndatalogtoday.org/ is also a good source of datalog examples
@ramblurr in the slides, they are using map syntax for defining the query, it’s not a typo.
Can’t find great docs on map vs vector queries but it is mentioned here https://docs.datomic.com/on-prem/clojure/index.html#datomic.api/q
Note the use of {}
not []
below to define the query
Ah that explains then why the rule is in a vector. There needs to be a pair so the value of the :where key is wrapped in a vector, other where clausee would presumably go inside that vector (in their own vector)