Hi, As you mentioned in another thread, your version of defblockfn cannot create more than one macro due to the problem with defn. I also didn't see whether it was interesting to have the explicit defn, I thought that an anonymous function could do the trick. And as I, too, wanted to understand more thouroughly how nested syntax-quotes ... work, I tried and (and finally arrived to!) a working solution.
Here it is (with first the demonstration of the problem in the original defblockfn) (note that I also gensymed all the intermediate macro params, though it may not be needed in this particular case, since the user code itself is encapsulated in an anonymous fn and will not be in the lexical scope where the non gensymed params are placed in your version) : ;; initial defblockfn ... (defmacro defblockfn [function params & body] (let [butlast_params (butlast params)] `(do (defn func# ~params ~...@body) (defmacro ~function [...@butlast_params & tail#] `(~'func# ~...@butlast_params (fn [] ~...@tail#)))))) ;; ... does not work well if more than one macro is generated (defblockfn with-1 [text-before text-after func] (println "before:" text-before) (func) (println "after:" text-after)) (defblockfn with-2 [text-before text-after func] (println "avant:" text-before) (func) (println "apres:" text-after)) (with-1 "before" "after" (println "middle")) (with-2 "before" "after" (println "middle")) ;; working defblockfn ... (defmacro defblockfn [function params-names & body] (let [macro-params-names (map (fn [_] (gensym)) (butlast params-names))] `(defmacro ~function [...@macro-params-names & macro-tail#] `((fn [~@'~params-names] ~@'~body) ~@(list ~...@macro-params-names) (fn [] ~...@macro-tail#))))) ;; ... does work well if more than one macro is generated (defblockfn with-1 [text-before text-after func] (println "before:" text-before) (func) (println "after:" text-after)) (defblockfn with-2 [text-before text-after func] (println "avant:" text-before) (func) (println "apres:" text-after)) (with-1 "before" "after" (println "middle")) (with-2 "before" "after" (println "middle")) HTH, -- Laurent 2009/5/28 CuppoJava <patrickli_2...@hotmail.com>: > > Okay. So I grasped some understanding from going through Meikel's > macro with a micron comb. > > Here's my version: it's a little more general (it can accept any > number of arguments), and little cleaner. > ---------------- > (defmacro defblockfn [function params & body] > (let [butlast_params (butlast params)] > `(do (defn func# ~params ~...@body) > (defmacro ~function [...@butlast_params & tail#] > `(~'func# ~...@butlast_params (fn [] ~...@tail#)))))) > ----------------- > > This allows us to define "modifier" macros, like such: > > (defblockfn with_surrounding_text [text func] > (println text) > (func) > (println text)) > > And you can use it like such: > > (with_surrounding_text "surround" > (println "within surrounding text: line1") > (println "within surrounding text: line2")) > > I'm personally using it to wrap openGL commands: > (defblockfn with_shape [shape func] > (glBegin shape) > (func) > (glEnd)) > > so that I can type: > > (with_shape GL11/GL_QUADS > (glVertex ...) > (glVertex ...)) > > The point of this macro is not to accomplish any specific function. > It's to allow you to define your own "wrapping" functions. > > Thanks to Meikel and Sean for their input and help. > -Patrick > > > --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---