Skip to content

Instantly share code, notes, and snippets.

@alandipert
Last active December 30, 2015 19:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alandipert/73e923a690061d18ba3a to your computer and use it in GitHub Desktop.
Save alandipert/73e923a690061d18ba3a to your computer and use it in GitHub Desktop.
Use Datomic Datalog to query arbitrary map-like structures.
(set-env! :dependencies '[[com.datomic/datomic-free "0.9.5344"]])
(require '[datomic.api :refer [db q] :as d])
(defn paths
"Enumerate paths into a nested map/vector."
([root]
(when (or (map? root) (vector? root))
(paths [] root)))
([parent x]
(cond (map? x)
(mapcat (fn [[k v]] (paths (conj parent k) v)) x)
(vector? x)
(mapcat #(paths (conj parent %1) %2) (range) x)
:else [parent])))
(defn map->tuples
"Returns every path and value in the map as a set of tuples, optionally
prefixing each with an id number."
([m]
(->> (paths m)
(mapv #(conj % (get-in m %)))))
([id m]
(->> (map->tuples m)
(mapv #(into [id] %)))))
(def maps
[{:name "bob"
:age 43
:kids ["susan" "clarence"]}
{:name "joe"
:age 32
:kids ["joyce"]}])
(def tuples
(mapcat #(map->tuples %1 %2) (range) maps))
(q '[:find ?name
:where
[?id :kids _ "susan"]
[?id :name ?name]]
tuples)
;; #{["bob"]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment