Fork me on GitHub
#datahike
<
2021-02-25
>
Casey16:02:22

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?

kkuehne14:02:41

Hey @U70QFSCG2, let me check this myself and get back to you. So the query works with Datomic right?

Casey14:02:54

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

kkuehne15:02:50

Ok, where does the owns? function come from?

kkuehne15:02:33

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.

Casey15:02:25

(def rules
    '[[(owns? ?uid ?e)
       [?e :auth/owner ?user]
       [?user :account/id ?uid]]
That is the "declaration" of the (owns?...) rule.

kkuehne17:02:44

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.

pithyless17:02:11

@U70QFSCG2 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

Casey19:02:22

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.

pithyless21:02:19

@U70QFSCG2 if you haven't seen it, http://www.learndatalogtoday.org/ is also a good source of datalog examples

Josh22:02:32

@U70QFSCG2 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

Casey07:02:49

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)