Fork me on GitHub
#datalog
<
2020-08-26
>
Ben Sless14:08:58

Hi all, I want to write a query with a rule like

(or
 [?e :entity/a1 ?v1]
 [?e :entity/a2 true])
Where ?v1 is a parameter. Datomic throws on it because all or clauses must use same set of vars. Kondo also diagnoses a problem there that "join variable is not declared inside clauses" Any way to do it besides add a negation?
(or
 [?e :entity/a1 ?v1]
 (and
  (not [?e :entity/a1 ?v1])
  [?e :entity/a2 true]))

Joe Lane14:08:36

@ben.sless For the datomic case, I would suggest looking at rules. If you're on cloud, https://docs.datomic.com/cloud/query/query-data-reference.html#rules is the reference docs. Specifically, you're looking for this subsection https://docs.datomic.com/cloud/query/query-data-reference.html#multiple-rule-heads

metal 3
Joe Lane14:08:26

Rules allow disjunction

Ben Sless14:08:58

Well, that was surprisingly painless, thanks @lanejo01! This worked:

[[(pred ?e ?v1)
  [?e :entity/a1 ?v1]]
 [(pred ?e ?v1)
  [?e :entity/a2 true]]]

👏 3
Joe Lane14:08:54

Just curious, was there a reason you didn't post this question in the datomic channel?

Ben Sless14:08:27

Yes, because I did not know if it was specific to datomic's implementation or if I was thinking about datalog wrong

Ben Sless14:08:48

I tend to think it's the latter

Joe Lane14:08:15

Thanks for the info!

🙂 3
Ben Sless14:08:05

A nice bonus is that it performs faster than my previous version which used negation

Joe Lane14:08:19

If you run into more issues while using datomic, feel free to reach out on the #datomic channel, there are ~2000 Members in that channel, as opposed to 134 here. I presume folks here will have a very deep understanding of datalog, but the question you asked would be answerable by most who use datomic in anger. Please reach out if you have any more questions, good luck and have fun!

Ben Sless15:08:51

🙏 thank you!

quoll15:08:38

Out of curiosity, assuming that you don’t need ?v1 then would it work to use:

(or
 [?e :entity/a1]
 [?e :entity/a2 true])

quoll15:08:14

I don’t know if the first part of the or clause creates an internal “hidden” variable (which could result in it not working), or if it just doesn’t leave it bound. If it’s the latter, then it should work, but if it’s the former then it still have the problem

Casey18:08:55

A side project I'm working on is a clojure implementation of a turn based game. It's quite complex, with lots of state. Up until now I've been keeping the state in a big nested map. On one hand this works great as the game logic consists of only pure functions. But I've started amassing quite a pile of little functions to get and update the state. It's a mix of vanilla clojure and specter. I recently just re-organized the state to be normalized with most entities at the top level, using ids to reference relations. This simplified some of my grab bag functions, but there are still quite a few and they are gnarly. I'm pondering switching to datascript to dump the state into and query. Since processing all happens in memory, I'd simply deserialize, process, and serialize the game state. No need for datomic. But I'm wondering about schema migrations. Once the single source of truth is a datascript db and I can't change the schema.. this seems like a bad idea. Any thoughts from ya'll?

quoll20:08:49

At the risk of sounding self-serving, you could always try Asami. It does not use a schema, and the queries work similarly