Skip to content

Latest commit

 

History

History
307 lines (244 loc) · 8.82 KB

2020-07-03.md

File metadata and controls

307 lines (244 loc) · 8.82 KB

Learning Clojure in Public - Week 2 Day 5 (12/35)

Expectations

Today I am taking a break from the books, even though I just started Clojure for the Brave and True. The expectation is to get a basic understanding of Datalog by going through some chapters of https://learndatalogtoday.com in the hope that it will help me research our first Athens issue as a cohort.

Once that is done, I will use that knowledge to look into that issue. We're 3 looking into it at the moment, and I'd like us to move forward at the same time. Time difference and time available to look into it might be an issue but if we're diligent we will all get something out of it.

What I learned

Datalog

Learn Datalog Today Exercises

Chapter 1
Exercise 0: Find the entity ids of movies made in 1987
[:find ?e
 :where
 [?e :movie/year 1987]]
Exercise 1: Find the entity-id and titles of movies in the database
[:find ?e ?title
 :where
 [?e :movie/title ?title]]
Exercise 2: Find the name of all people in the database
[:find ?name
 :where
 [?e :person/name ?name]]
Chapter 2
Exercise 0: Find movie titles made in 1985
[:find ?title
 :where
 [?m :movie/year 1985]
 [?m :movie/title ?title]]
Exercise 1: What year was "Alien" released?
[:find ?year
 :where
 [?m :movie/title "Alien"]
 [?m :movie/year ?year]]
Exercise 2: Who directed RoboCop? You will need to use [ :movie/director ] to find the director for a movie.
[:find ?name
 :where
 [?m :movie/title "RoboCop"]
 [?m :movie/director ?n]
 [?n :person/name ?name]]
Exercise 3: Find directors who have directed Arnold Schwarzenegger in a movie.
[:find ?name
 :where
 [?e :person/name "Arnold Schwarzenegger"]
 [?m :movie/cast ?e]
 [?m :movie/director ?d]
 [?d :person/name ?name]]
Chapter 3
Exercise 0: Find movie title by year
[:find ?title
 :in $ ?year
 :where
 [?m :movie/year ?year]
 [?m :movie/title ?title]]
Exercise 1: Given a list of movie titles, find the title and the year that movie was released.
[:find ?title ?year
 :in $ [?title ...]
 :where
 [?m :movie/title ?title]
 [?m :movie/year ?year]]

####### Exercise 2: Find all movie ?titles where the ?actor and the ?director has worked together

[:find ?title
 :in $ ?actor ?director
 :where
 [?d :person/name ?director]
 [?a :person/name ?actor]
 [?m :movie/director ?d]
 [?m :movie/cast ?a]
 [?m :movie/title ?title]]
Exercise 3: Write a query that, given an actor name and a relation with movie-title/rating, finds the movie titles and corresponding rating for which that actor was a cast member.
[:find ?title ?rating
 :in $ ?actor [[?title ?rating]]
 :where
 [?a :person/name ?actor]
 [?m :movie/cast ?a]
 [?m :movie/title ?title]]
Chapter 4
Exercise 0: What attributes are associated with a given movie.
[:find ?attr
 :in $ ?title
 :where
 [?m :movie/title ?title]
 [?m ?a]
 [?a :db/ident ?attr]]
Exercise 1: Find the names of all people associated with a particular movie (i.e. both the actors and the directors)
[:find ?name
 :in $ ?title [?attr ...]
 :where
 [?m :movie/title ?title]
 [?m ?attr ?p]
 [?p :person/name ?name]]
Exercise 2: Find all available attributes, their type and their cardinality. This is essentially a query to find the schema of the database. To find all installed attributes you must use the :db.install/attribute attribute. You will also need to use the :db/valueType and :db/cardinality attributes as well as :db/ident.
[:find ?attr ?type ?card
 :where
 [_ :db.install/attribute ?a]
 [?a :db/valueType ?t]
 [?a :db/cardinality ?c]
 [?t :db/ident ?type]
 [?c :db/ident ?card]
 [?a :db/ident ?attr]]
Exercise 3: When was the seed data imported into the database? Grab the transaction of any datom in the database, e.g., [_ :movie/title _ ?tx] and work from there.
[:find ?inst
 :where
 [_ :movie/title _ ?tx]
 [?tx :db/txInstant ?inst]]
Chapter 5
Exercise 0: Find movies older than a certain year (inclusive)
[:find ?title
 :in $ ?year
 :where
 [?m :movie/title ?title]
 [?m :movie/year ?y]
 [(>= ?year ?y)]]
Exercise 1: Find actors older than Danny Glover
[:find ?actor
 :where
 [?d :person/name "Danny Glover"]
 [?d :person/born ?dannybirth]
 [?cast :person/born ?byear]
 [_ :movie/cast ?cast]
 [(< ?byear ?dannybirth)]
 [?cast :person/name ?actor]]
Exercise 2: Find movies newer than ?year (inclusive) and has a ?rating higher than the one supplied
[:find ?title
 :in $ ?year ?rating [[?title ?r]]
 :where
 [?m :movie/year ?myear]
 [(>= ?myear ?year)]
 [(> ?r ?rating)]
 [?m :movie/title ?title]]
Chapter 6
Exercise 0: Find people by age. Use the function tutorial.fns/age to find the age given a birthday and a date representing "today".
[:find ?name
 :in $ ?age ?today
 :where
 [?p :person/name ?name]
 [?p :person/born ?born]
 [(tutorial.fns/age ?born ?today) ?age]]
Exercise 1: Find people younger than Bruce Willis and their ages.
[:find ?name ?age
 :in $ ?today
 :where
 [?p :person/name ?name]
 [?b :person/name "Bruce Willis"]
 [?b :person/born ?bruceborn]
 [?p :person/born ?born]
 [(> ?born ?bruceborn)]
 [(tutorial.fns/age ?born ?today) ?age]]
Exercise 2: The birthday paradox states that in a room of 23 people there is a 50% chance that someone has the same birthday. Write a query to find who has the same birthday. Use the < predicate on the names to avoid duplicate answers.
[:find ?name-1 ?name-2
 :where
 [?p1 :person/name ?name-1]
 [?p2 :person/name ?name-2]
 [?p1 :person/born ?born-1]
 [?p2 :person/born ?born-2]
 [(.getMonth ?born-1) ?m]
 [(.getMonth ?born-2) ?m]
 [(.getDate ?born-1) ?d]
 [(.getDate ?born-2) ?d]
 [(< ?name-1 ?name-2)]]

Troubleshooting our first issue

The current code for indenting a node is living in events.cljs.

(reg-event-fx
  :indent
  (fn [_ [_ uid]]
    (let [block (get-block [:block/uid uid])
          parent (get-parent [:block/uid uid])
          older-sib (->> parent
                      :block/children
                      (filter #(= (dec (:block/order block)) (:block/order %)))
                      first
                      :db/id
                      get-block)
          new-block {:db/id (:db/id block) :block/order (count (:block/children older-sib))}
          reindex-blocks (->> (d/q '[:find ?ch ?new-o
                                     :in $ % ?p ?at
                                     :where (dec-after ?p ?at ?ch ?new-o)]
                                @db/dsdb rules (:db/id parent) (:block/order block))
                           (map (fn [[id order]] {:db/id id :block/order order})))]
      {:transact [[:db/retract (:db/id parent) :block/children (:db/id block)]
                  {:db/id (:db/id older-sib) :block/children [new-block]} ;; becomes child of older sibling block — same parent but order-1
                  {:db/id (:db/id parent) :block/children reindex-blocks}]}))) ;; reindex parent

In the let statement several things are computed: block and parent are self-explanatory, older-sib is the node above at the same level, new-block is where the block will be post indent, and reindex-blocks will make sure the order is right after the block has moved. But all this doesn't matter because if the block doesn't have any older siblings, we can just not run the transact. We don't even have to evaluate the let itself. The code becomes:

(fn [_ [_ uid]]
   (let [block (get-block [:block/uid uid])
         parent (get-parent [:block/uid uid])]
+     (if (= (:block/order block) 0)
+       {}
       (let [older-sib (->> parent
                            :block/children
                            (filter #(= (dec (:block/order block)) (:block/order %)))
                            first
                            :db/id
                            get-block)

Takeaways

All in all, I didn't need to study datalog at all for this issue but it will be useful for the future. Still I feel like I will be able to get back to the solutions to these exercises, and use them as reference in the future.

Understanding the issue was possible with the basic knowledge of clojure that I have acquired in the past 10 days or so (it feels great!). Let's end the day with a tally of what I completed:

  • First 7 chapters of Learn Datalog Today, with all its exercises
  • Identified half of the solution for our first collaborative issue in the Athens codebase