Datalog in JavaScript
instantdb.dev
instantdb.dev
- There are several such talks at https://www.hytradboi.com/ (happening this Friday)
- Roam Research and its clones Athens, Logseq, use Datascript / ClojureScript https://github.com/tonsky/datascript
- differential-datalog isn’t an end-to-end system, but is highly optimized for quick reactivity https://github.com/vmware/differential-datalog
- Datalog UI is a Typescript port of some of differential-datalog’s ideas https://datalogui.dev/
I think an under appreciated aspect of Datalog is as a pure specification language for relationships. Schema languages like GraphQL specify a relation between types exists, but not how it is computed. Prisma and other ORM DSLs like ActiveRecord do a better job specifying how to compute a relation from SQL tables, but support only a few strict computation types that can be modeled using SQL JOIN on columns.
Datalog lets you purely specify arbitrarily complex logical relationships between data types. Even if you were to only use Datalog as a rules engine at test time, it could still be quite powerful for validating logic implemented in different languages on the same data model, to say keep your Typescript, Kotlin and Swift logic in sync.
I do feel saddened that few seem to realise that the fundamental idea actually comes from RDF (i.e. the semantic web) and that Datomic's Datalog dialect is actually very similar to SPARQL. Datomic's primary innovation is the immutability/time travel feature, not the fact that is uses triples and works like a graph database. If you find triplestores fascinating I implore you to explore the semantic web stack too.
While RDF has an elegant core, it is bogged down by the complixity of the web and ancillary technologies.
XML Types, cURIes, OWL, the different encodings.
They all make RDF a nightmare to work with, and to implement in practice.
The is simply no good RDF software ecosystem, yet the Spec ecosystem continues to grow (wildly out of control).
On a technical note, SPARQL and Datomic Datalog are very different beasts.
The former is conjunctive queries with optionals and regular path expressions (i.e. Conjunctive queries + XPath + nonmonotonic defaults) while the latter is recursive conjunctive queries (i.e. Datalog).
Of course there are other GraphDBs with additional properties and custom query languages such as Neo4j and its query language Cypher. I Find that Neo4j's property graph is more intuitive to model data with than a plain RDF store and Cypher has some advantages over SPARQL as well
The author conflates Datomic family databases which use triples as their data model and datalog as their query engine, with datalog the pure prolog subset / conjunctive query + recursion fragment.
Not a great start for a novel DB product...
As a curiosity... I implemented a very simple toy triplestore in Kotlin that used AVL TreeSets. [2] (only the storage layer, it has no other querying than a simple for-loop like mechanism :-) ).
1: https://github.com/SWI-Prolog/packages-semweb/blob/master/do...
2: https://gist.github.com/EmmanuelOga/1d52adb79bdb6092fb698ed5...
You 'd have to implement some sort of stratification to effectively make sure Datalog stays Turing incomplete when allowing for recursion.
Some form of stratification is usually required when you add Negation (which the demo also doesn't seem to have). But even here it's not because the language would become Turing complete, but rather to ensure that it has a consistent semantics. Consider, e.g., a program with two rules: `A :- not B`, `B :- not A`. Unlike Datalog programs, this does not have a unique minimal model, since both `{A}` and `{B}` are minimal models. Stratification is then a syntactic restriction that prevents such situtations.
Entailment in Datalog is monotonic in the sense that once a fact has been derived by the program, no further rule application can invalidate this fact (this is no longer true when adding negation, and is indeed what we recover by stratifying).
Taken together, this means that you can always compute all facts derived by a Datalog program on a database by computing the least fixed point under immediate consequences (roughly “apply all rules and add the derived facts”; this approach is called “naive evaluation” in the literature, in practice, more optimised evaluation strategies are useful), and you are guaranteed to obtain this after polynomially many (with respect to the database) or exponentially many (with respect to the program) steps – every step derives at least one fact; once you have reached a state where there are no more immediate consequences, you have derived every fact that you will ever derive and can stop.
https://github.com/nezaj/clj-sicp/blob/master/src/logic_inte...
(The main ingredient, if I remember correctly, was `unify-match`)
I still haven’t found the activation energy, though.