See the clojure.walk namespace. It has macroexpand-all and walk/ prewalk functions which would make this much simpler.
That said: yes, of course there is a form that introduces lexical bindings; it's called let (as shown in Mike Meyers's solution). On Feb 10, 8: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))) > > ;;After that convenience function, the macro that I actually wanted to > write is trivial! > (def *bindings*) > (defmacro do-binding [& body] > `(let ~*bindings* ~@body)) > (defmacro bind-later [bindings & body] > (binding [*bindings* bindings] > (macroexpand-full `(do ~@body)))) > > Thanks for all your ideas! > -Patrick > > On Feb 10, 2:19 am, Mike Meyer <[email protected]> wrote: > > > On Wed, 9 Feb 2011 20:34:56 -0800 (PST) > > > CuppoJava <[email protected]> wrote: > > > Description: (bind-later bindings & body) and (do-binding & body) > > > (bind-later) is used like a let-form, except that it doesn't > > > *immediately* make the bindings available. > > > The bindings become available only within (do-binding). > > > (do-binding) is always used within a (bind-later). > > > > Here's some sample code showing how it works. > > > > (def a "outer a") > > > (bind-later (a "inner a") > > > (println a) <-- this prints out "outer a" still. > > > (do-binding > > > (println a))) <-- this will print out "inner a" > > > > Is such a macro possible? > > > Yes. It's just - as you say - tricky. You need to create a > > "do-binding" macro for each bind-later macro, meaning it should be > > part of the macros lexical space. First trick - use > > clojure.contrib.macro-utils/macrolet to do that sanely. Then comes the > > really tricky part - figuring out the correct unquoting for everything. > > But this does it: > > > (defmacro bind-later [bindings & body] > > `(macrolet [(~'do-binding [& body#] > > `(let ~'~bindings > > ~@body#))] > > ~@body)) > > > Oh, one thing - since let requires a vector for binding, your example > > has to be written as (bind-later [a "inner a"] .... But that's the > > standard clojure idiom for bindings, so you should do it that way > > anyway ;-). > > > <mike > > -- > > Mike Meyer <[email protected]> http://www.mired.org/consulting.html > > Independent Network/Unix/SCM consultant, email for more information. > > > O< ascii ribbon campaign - stop html mail -www.asciiribbon.org > > -- 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
