Fork me on GitHub
Steven Deobald01:06:59 => To see this, let's look for all of the _*:first-name*_s again. ... renders a little weirdly on GitHub. Took me a minute to parse "Part 1/2" ~= "Pattern 1 / 2" (in the table) in this section: ... maybe labels on the patterns themselves would help with clarity? (Ditto Part 3... though I think by the time a person gets that far, the references to the query triples is obvious.) @quoll This is a great intro! I don't think I've seen these kinds of query / image pairings before. They really do a nice job of demonstrating what each clause is doing. 🙂


Thanks for the first one. Fixed. The second one… I was just breaking it down into parts… it didn’t occur to me exactly that there was a one-to-one with patterns. Should I rename the sections “Pattern 1”, “Pattern 2", “Pattern 3”?

Steven Deobald01:06:24

That would work too, yup.

Steven Deobald01:06:57

It's not as though it's impenetrable as-is... but it did cause me to backtrack on my first pass.


I’m kinda running on fumes right now. I started it yesterday afternoon, and finished it this evening.


Oh, I know why I was calling it parts! I have a bullet point list of the requirements, and I was aligning it with that!

Steven Deobald01:06:58

It's very readable. It's late, 35 degrees celsius, and I'm full of hamburgers. But I could still breeze through it nodding "yup, yup" to myself the whole way.

Steven Deobald01:06:26

Ah, in the Goal section


but it aligns with patterns already. So I’m good making the change (already done)

🚀 3
Steven Deobald02:06:02

Looking forward to the next instalment. 🙂


I gave me 2 days off writing code, so it was a nice change


I’ve been meaning to write it for a while, but when a colleague said that they didn’t really get these graph queries, then I decided that I had to get it done


I’ve been hearing from friends with ADHD recently that colored images help them stay connected with the material, so I worked on that a lot


It’s SOOOO tempting to put more and more and more info in there


Like… I want to compare these patterns to SPARQL Basic Graph Patterns (BGPs), because they’re basically the same


which also explains how I want to extend the syntax to work like that



[:find ?title
 :where {:first-name "Sally"
         :last-name "Smith"
         :title ?title}]
SELECT ?title
WHERE {:first-name "Sally";
       :last-name "Smith";
       :title ?title}


equivalent to:

[:find ?title
 :where [?n :first-name "Sally"]
        [?n :last-name "Smith"]
        [?n :title ?title]]

Steven Deobald02:06:14

I think unless Asami actually works like that, I wouldn't include alternate syntax in your intro guide... I could definitely see that get confusing for new users.


Oh goodness, no! Sorry… that was me going off on a wild tangent!

😅 3
Steven Deobald02:06:37

Relatedly, I have been fantasizing about writing up a SPARQL / Datalog / edn Datalog flavours (Datomic, Asami, Crux) / SQL comparison sheet.


Asami doesn’t do that now, though I’d like it to. But if it did do that then I still would not put it into an introduction


That intro document specifically avoids a LOT


It doesn’t show any of the projection options (in fact, I kind of gloss over the return type of the q function)


It doesn’t show filter, or aggregates, or any of that stuff


If you give a person too much in one go, then it’s too much


I wanted to get the reader to a point of issuing basic but useful queries


I think that once you have a handle on how patterns and conjunctive joins work, then the rest of it comes much easier


I wasn’t even going to include the _ syntax until I realized that it helped me to explain the template nature of the patterns

👍 3

Also, my colleague who was struggling with it explained that seeing ?varname everywhere was the most confusing part


The ? characters were throwing them off

Steven Deobald02:06:36

I agree. The concepts are actually surprisingly simple for a first-time user, which can be confusing in its own right. If someone is accustomed to cobbling together lumpy SQL queries, tiny clauses each potentially representing its own join can feel pretty alien.


So I tried to introduce variables more carefully, and I was told that it worked. (whew!)


Yes… this is a thing that has frustrated me for many years. It’s actually quite simple (as in, there are few connected parts), and yet it still eludes many people.

Steven Deobald02:06:15

> The ? characters were throwing them off I had this problem too, back in 2014. I couldn't actually say why, though. Like, I understood what the ?var pattern meant, intellectually, but I couldn't visually parse it for the longest time.

Steven Deobald02:06:43

> as in, there are few connected parts Yeah, it's a bit of a paradox. Because we're so accustomed to more complex query languages, we're expecting complications where there aren't any.


When we built TQL (Tucana Query Language) for Tucana/Kowari/Mulgara then we used $ instead. But then RDQL (RDF Data Query Language) used ?. So when SPARQL first came out it allowed either (committees FTW!)


I think the popularity of Jena made most people move towards the ? syntax


I don’t know why Rich went that way though. Maybe because SPARQL tends to use it? He did say that it was an influence


BTW, Asami is basically a SPARQL engine that uses edn for parsing 🙂

Steven Deobald02:06:09

Makes sense. Hakan said the Crux Datalog implementation had a massive SPARQL overlap, too.

Steven Deobald02:06:52

We just adapted the Learn Datalog Today tutorial to Crux: (right hand side) ... but I'm realizing that the visuals you've come up with here are actually better introductory material.

Steven Deobald02:06:06

I actually think a middle-ground between the two approaches would be a lot of fun.


I’ve been thinking that I need to bring in Instaparse and parse SPARQL. It can just generate Clojure data structures, and it will work

Steven Deobald02:06:58

"Solve for XYZ query, execute it, and see the small graph visualization on the other side of the screen highlight what you've done." kind of thing.


That would be nice!


BTW, you’re going to see me studiously avoiding the use of the term “Datalog” 🙂

Steven Deobald02:06:52

Need some GSoC students to build these fun toys.

👍 3
Steven Deobald02:06:24

Ha! Fair. I think we've progressively started labelling it "EDN Datalog" more and more often internally.


I could live with that


I only know of a single Clojure implementation of


(Note that my link is to the “Syntax” portion of that page)

Steven Deobald02:06:46

Yeah, I was harassing Hakan for a Crux parser that could handle horn clauses much earlier, but his pushback is that there isn't a good standard for "true" Datalog syntax anyway... which feels like a legitimate reason not to chase it. He basically made me read the What you Always Wanted to Know About Datalog (And Never Dared to Ask) paper and I gave up. 😉


Lol. That’s VERY old!


I have it somewhere printed out


From the early 2000s


BTW, if you know of any other Datalog parsers in Clojure I’d be interested please


I think that’s true; I suspect it’s compounded by the fact that it’s usually a subset of prolog syntax. And prolog syntax is ISO standardised; but you have to pay to access the standard, and can’t republish it, and consequently can’t really define a proper formal subset. So I suspect folk just hack something that works & looks like prolog.


Also I guess it’s rooted in academic literature; and academics are usually more interested in papers, and creating their own implementations than shared standards.


Morning, I was playing with some algorithms for top sorting, I just stumble upon a possible "issue" other users can meet:


(def db-uri "asami:")

(def data
  [{:db/ident :t1 :task/name "Task 1" :task/requires [{:db/ident :t3}]}
   {:db/ident :t2 :task/name "Task 2" :task/requires [{:db/ident :t1}]}
   {:db/ident :t3 :task/name "Task 3" :task/requires [{:db/ident :t1} {:db/ident :t2}]}
   {:db/ident :t4 :task/name "Task 4" :task/requires [{:db/ident :t2} {:db/ident :t3}]}
   {:db/ident :j1 :job/name "Job 1"}])

(defn build-db
  (d/create-database db-uri)
  (let [conn (d/connect db-uri)]
    (d/transact conn data)
    (d/entity (d/db conn) :t3 true)))


Expanding :t3 results in a Execution error (StackOverflowError) at zuko.schema/eval9645$vartest? (schema.cljc:35). null


Probably it's not an Asami duty to inform the user that the graph is circular


But it can happen


Oh…. I have entity loading based on our datasets, and it never occurred to me to worry about that. Thank you!