Skip to content

Instantly share code, notes, and snippets.

@whilo
Created April 7, 2017 23:29
Show Gist options
  • Save whilo/dd976d206a814332ed6d6b29c63a6c48 to your computer and use it in GitHub Desktop.
Save whilo/dd976d206a814332ed6d6b29c63a6c48 to your computer and use it in GitHub Desktop.
(ns datanaive.core)
;; https://courses.cs.washington.edu/courses/cse544/16au/lectures/lecture05-datalog.pdf
;; slide 7
;; Actor(344759,‘Douglas’, ‘ Fowley ’).
;; Casts(344759, 29851).
;; Casts(355713, 29000).
;; Movie(7909, ‘A Night in Armour ’, 1910).
;; Movie(29000, ‘Arizona’, 1940).
;; Movie(29445, ‘Ave Maria’, 1940).
(def actor {344759 {"Douglas" "Fowley"}})
(def casts {344759 29851
355713 29000})
(def movie {7909 {"A Night in Armour" 1910}
29000 {"Arizona" 1940}
29445 {"Ave Maria" 1940}})
(def q1 [[movie :x :y :z]
[= :z 1940]])
;; S elect- P roject- J oin- U nion query
(defn select [r]
(let [[relation v1 v2 v3] r]
(if-not (map? relation)
r ;; do nothing for intensional clauses
(for [[e m1] relation
[a v] m1]
(merge {v1 e v2 a}
(when v {v3 v}))))))
(defn extensional? [r]
(seq? r))
(defn intensional? [r]
(not (extensional? r)))
(defn join [r1 r2]
(when-not (or (extensional? r1)
(extensional? r2))
(throw (ex-info "Cannot join two intensional rules."
{:r1 r1 :r2 r2})))
(if-not (extensional? r1)
(recur r2 r1)
(if (extensional? r2)
:todo
(let [[pred a b] r2
[a b] (if (keyword? a) [a b] [b a])]
(assert (keyword? a))
(filter #(pred (a %) b) r1)))))
(join (select [movie :x :y :z])
[= :z 1940])
(defn project [vars frames]
(map #(select-keys % vars) frames))
(defn query [vars q]
;; TODO cover union over OR clauses
(->> q
(map select)
(apply join)
(project vars)))
(query #{:x :z} q1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment