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 <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)))
>
> ;;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 <m...@mired.org> wrote:
>
> > On Wed, 9 Feb 2011 20:34:56 -0800 (PST)
>
> > CuppoJava <patrickli_2...@hotmail.com> 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 <m...@mired.org>          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 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