On Thu, Feb 10, 2011 at 11:01 AM, CuppoJava <patrickli_2...@hotmail.com> wrote: > Thanks for all your help everyone! > > So I came up with an elegant solution. It was a combination of > Meikel's codwalker solution gave me the idea to bootstrap off of > Clojure's macroexpand system to get it to work. > > ;;This is a convenience method for expanding macros. It recursively > ;;macroexpands every subform within a form. > (defn macroexpand-full [expression] > (let [expanded (macroexpand expression)] > (cond > ;;Normal Form > (or (seq? expanded) (list? expanded)) > (doall (map macroexpand-full expanded)) > > ;;Vector Form > (vector? expanded) > (vec (map macroexpand-full expanded)) > > ;;Map Form > (map? expanded) > (into {} (map macroexpand-full expanded)) > > ;;Set Form > (set? expanded) > (into #{} (map macroexpand-full expanded)) > > ;;Atom > :else > expanded)))
What a coincidence. I just had reason to write my own version of this. I came up with a somewhat different approach though: (defn map-ps [f coll] (if (map? coll) (into (empty coll) (map (fn [[k v]] [(f k) (f v)]) coll)) (if (or (vector? coll) (set? coll)) (into (empty coll) (map f coll)) (map f coll)))) (defn macroexpand-all [form] (if (coll? form) (let [f (macroexpand form)] (if (coll? f) (map-ps macroexpand-all f) f)) form)) The helper function map-ps maps a function over any set, map, vector, or seq/list, preserving the type and applying to both keys and values of maps. (It should even turn a sorted-set, say, into a sorted-set with the same comparator. That may actually work poorly in certain cases where the types of the elements are changed. But that's not relevant for macroexpand-all. Meanwhile all lists/seqs become LazySeq.) The actual macroexpand-all function exploits macroexpand, as does your implementation, but uses map-ps to recursively apply itself to subforms. I didn't bother with doall because typical Clojure code does not nest thousands of parentheses deep. :) -- 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