(defn topo-sort
"Returns a topologically-sorted list of nodes in graph."
[graph]
(loop [sorted ()
g graph
todo (set (filter #(empty? (immediate-dependents graph %))
(nodes graph)))]
(if (empty? todo)
sorted
(let [[node & more] (seq todo)
deps (immediate-dependencies g node)
[add g'] (loop [deps deps
g g
add #{}]
(if (seq deps)
(let [d (first deps)
g' (remove-edge g node d)]
(if (empty? (immediate-dependents g' d))
(recur (rest deps) g' (conj add d))
(recur (rest deps) g' add)))
[add g]))]
(recur (cons node sorted)
(remove-node g' node)
(clojure.set/union (set more) (set add)))))))