On Thu, Feb 10, 2011 at 11:01 AM, CuppoJava <[email protected]> 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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en