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