You can pretty much call anything outside of the quote, in fact all runtime
information is available (you have access to anything that was previously
read).  The main thing to understand is that all parameters passed to your
macro are unevaluated.

On Sat, Feb 14, 2009 at 10:45 AM, samppi <rbysam...@gmail.com> wrote:

>
> Thank you so much. I'm confused, however, about what functions you're
> allowed to call inside a macro outside of a quote. I read once that
> "runtime information" was unavailable during the macro phase. But it
> seems that one is still allowed to call array-map, apply, take-nth,
> and vec during the macro phase. What is the pattern for what is
> allowed or prohibited in macros?
>
> On Feb 13, 10:52 pm, Chouser <chou...@gmail.com> wrote:
> > On Fri, Feb 13, 2009 at 11:17 PM, samppi <rbysam...@gmail.com> wrote:
> >
> > > I'm trying to write a macro that expands from this:
> >
> > > (product-context [n rule0, m rule1)]
> > >  (rule-maker2 (+ n m)) rule3))
> >
> > > Into this (assume that conc-fn and conc-products are functions):
> >
> > > (fn [tokens]
> > >  (if-let [[remainder# n m] (conc-products [rule0 rule1] tokens)]
> > >    (conc-fn [(rule-maker2 (+ n m)) rule3] remainder#)))
> > > ...but I can't figure out how to change [n rule0 m rule1] to (if-let
> > > [[remainder# n m] (conc-products [rule0 rule1] tokens)] ...).
> >
> > Try working it out outside of the macro context.
> >
> > (def bindvec '[n rule0, m rule1])
> >
> > Now you've got something to work with.  There are plenty of acceptible
> > answers.  Maybe you want to think of the vector as key/value pairs:
> >
> > (apply array-map bindvec)  ==> {n rule0, m rule1}
> > (keys (apply array-map bindvec))  ==> (n m)
> > (vals (apply array-map bindvec))  ==> (rule0 rule1)
> >
> > Or just use some seq function:
> >
> > (take-nth 2 bindvec)  ==> (n m)
> > (take-nth 2 (rest bindvec))  ==> (rule0 rule1)
> >
> > Once you've got the pieces you need, try sticking them into a
> > syntax-quote:
> >
> > user=> `(if-let [[r# ~(take-nth 2 bindvec)] (cp ~(take-nth 2 (rest
> > bindvec)))] ...)
> > (clojure.core/if-let [[r__215__auto__ (n m)] (user/cp (rule0 rule1))]
> ...)
> >
> > Well, that's close by there are extra parens around (n m) and you want
> > a vector not a list for the rules.  So play with it until it looks
> > right:
> >
> > user=> `(if-let [[r# ~@(take-nth 2 bindvec)] (cp ~(vec (take-nth 2
> > (rest bindvec))))] ...)
> > (clojure.core/if-let [[r__219__auto__ n m] (user/cp [rule0 rule1])] ...)
> >
> > Then you're ready to build the macro:
> >
> > (defmacro product-context [bindvec & body]
> >   `(fn [tokens#]
> >      (if-let [[remainder# ~@(take-nth 2 bindvec)]
> >                 (conc-products [~@(take-nth 2 (rest bindvec))] tokens#)]
> >        (conc-fn [...@body] remainder#))))
> >
> > --Chouser
> >
>

--~--~---------~--~----~------------~-------~--~----~
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
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