Skip to content

Instantly share code, notes, and snippets.

@bendlas
Last active March 10, 2016 14:47
Show Gist options
  • Save bendlas/44d000a197c9e765d05b to your computer and use it in GitHub Desktop.
Save bendlas/44d000a197c9e765d05b to your computer and use it in GitHub Desktop.
block scoping for generating ids in edn
(require '[clojure.edn :as edn] '[clojure.zip :as zip] '[clojure.pprint :as pp])
(defrecord Kwid [kw])
(defrecord Dbid [part id])
(defn empty [o] ;; overwrite clojure's builtin, see http://dev.clojure.org/jira/browse/CLJ-1893
(if (instance? clojure.lang.MapEntry o)
[] (clojure.core/empty o)))
(def coll-zipper (partial zip/zipper coll? seq #(into (empty %1) %2)))
(defn replace-kwids [data]
(let [part (gensym "part-")]
(loop [dz (coll-zipper data)
seen {}]
(let [v (zip/node dz)]
(if (instance? Kwid v)
(if-let [id (get seen (:kw v))]
(recur (zip/replace dz id) seen)
(let [next-id (->Dbid part (inc (apply max -1 (map :id (vals seen)))))]
(recur (zip/replace dz next-id)
(assoc seen (:kw v) next-id))))
(if (zip/end? dz)
(zip/root dz)
(recur (zip/next dz) seen)))))))
(def read-testdata (partial edn/read-string
{:readers {'fresh replace-kwids
'kwid ->Kwid
'concat (partial apply concat)}}))
(pp/pprint
(read-testdata
"#concat
[#fresh [{:db/id #kwid :one
:data \"this is one/one\"
:link/to #kwid :two}
{:db/id #kwid :two
:data \"this is one/two\"
:link/to #kwid :one}]
#fresh [{:db/id #kwid :one
:data \"this is two/one\"
:link/to #kwid :two}
{:db/id #kwid :two
:data \"this is two/two\"
:link/to #kwid :one}]]"))
(comment ;; this should print (modulo gensyms):
({:link/to {:part part-45, :id 0},
:db/id {:part part-45, :id 1},
:data "this is one/one"}
{:link/to {:part part-45, :id 1},
:db/id {:part part-45, :id 0},
:data "this is one/two"}
{:link/to {:part part-46, :id 0},
:db/id {:part part-46, :id 1},
:data "this is two/one"}
{:link/to {:part part-46, :id 1},
:db/id {:part part-46, :id 0},
:data "this is two/two"}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment