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

Reply via email to