If deep nesting's not a concern, how about (defn process-node [node descendant-of-let?] (let [op (:op node) children (:children node) let-or-descendant? (or descendant-of-let? (= op :let)) processed-children (map #(process-node % let-or-descendant?) children) children (map first processed-children) constants (vec (apply concat (map second processed-children))) node (if descendant-of-let? (assoc node :unbox true) node)] (condp = op :fn [(assoc node :constants constants) constants] :let [node constants] :constant [node (conj constants {:value (:form node)})])))
(defn process-tree [root] (first (process-node root false))) Untested. Assumes that constants always are {:op :constant :form <value>}, i.e. the key with the desired value is always :form. If it's not, then that adds complication. How much depends on how the key is to be identified. Is it always the only other key besides :op? Then replace (:form node) on the last line above with (val (first (remove #(= (key %) :op) node))). Otherwise, something probably more complicated. It works by recursing, passing descendant-of-let? information down the stack, and accumulating constants up the stack. The implementation fn returns a two-element vector of the modified node and a vector of the constants in it (if a :op :constant node) and its descendants. Where it recurses it maps this over children and then uses (map first processed-children) and (map second processed-children) to extract the modified children themselves and the constant-vectors, respectively, and uses (vec (apply concat ...)) to convert the latter into a single vector with all the constants. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en