Skip to content

Instantly share code, notes, and snippets.

@tristanstraub
Last active February 7, 2018 00:06
Show Gist options
  • Save tristanstraub/93575d5b61611dcf0535d6fade0e8034 to your computer and use it in GitHub Desktop.
Save tristanstraub/93575d5b61611dcf0535d6fade0e8034 to your computer and use it in GitHub Desktop.
Compress clojure data structure -- find common subtrees and move them into a lookup table.
(ns trees
(:require [clojure.walk :as walk]))
(defonce id (atom 0))
(defrecord Ref [id])
(defn new-id! []
(->Ref (swap! id inc)))
(defmethod print-method Ref [this ^java.io.Writer w]
(.write w "#ref")
(.write w " ")
(print-method (:id this) w))
(defn hydrate
[{:keys [tree lookup]}]
(walk/prewalk-replace lookup tree))
(defn dehydrate
[tree]
(let [nodes (tree-seq coll?
#(if (map? %) (vals %) (seq %))
tree)
lookup (into {}
(->> nodes
frequencies
(remove #(<= (second %) 1))
#_ (remove #(<= (count (with-out-str (prn %)))
100))
(map #(vector (first %) (new-id!)))))]
{:tree (walk/prewalk-replace lookup tree)
:lookup (into {} (map (comp vec reverse) lookup))}))
#_ (prn (dehydrate {:a {:b 2} :x [{:b 2}]}))
#_ (prn (hydrate (dehydrate {:a {:b 2} :x [{:b 2}]})))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment