Skip to content

Instantly share code, notes, and snippets.

@Chouser
Created February 12, 2011 18:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Chouser/823958 to your computer and use it in GitHub Desktop.
Save Chouser/823958 to your computer and use it in GitHub Desktop.
Very raw version of a function to turn a seq into a lazy tree
(defn seq-tree
"Takes a sequential collection of events that logically represents
a tree by each event being one of: enter-sub-tree event,
exit-sub-tree event, or node event. Returns a lazy sequence whose
first element is a sequence of sub-trees and whose remaining
elements are events that are not siblings or descendants of the
initial event. The given exit? function must return true for any
exit-sub-tree event. parent must be a function of two arguments:
the first is an event, the second a sequence of nodes or subtrees
that are children of the event. parent must return nil or false if
the event is not an enter-sub-tree event. Any other return value
will become a sub-tree of the output tree and should normally
contain in some way the children passed as the second arg. The node
function is called with a single event arg on every node event and
its return value will become a node of the output tree.
(seq-tree #(when (= %1 :<) {:content %2}) #{:>} vector
[1 2 :< 3 :< 4 :> :> 5 :> 6])
;=> (([1] [2] {:content ([3] {:content ([4])})} [5]) 6)"
[parent exit? node coll]
(lazy-seq
(when-let [[event] (seq coll)]
(let [more (rest coll)]
(if (exit? event)
(cons nil more)
(let [tree (seq-tree parent exit? node more)]
(if-let [p (parent event (lazy-seq (first tree)))]
(let [subtree (seq-tree parent exit? node (lazy-seq (rest tree)))]
(cons (cons p (lazy-seq (first subtree)))
(lazy-seq (rest subtree))))
(cons (cons (node event) (lazy-seq (first tree)))
(lazy-seq (rest tree))))))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment