(defn topo-sort
([x get-deps]
(topo-sort x 0 (atom (sorted-map)) (memoize get-deps)))
([x depth state memo-get-deps]
(let [deps (memo-get-deps x)]
(swap! state update-in [depth] (fnil into #{}) deps)
(doseq [dep deps]
(topo-sort dep (inc depth) state memo-get-deps))
(doseq [[<depth _] (subseq @state < depth)]
(swap! state update-in [<depth] set/difference deps))
(when (= depth 0)
(distinct (apply concat (vals @state)))))))