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

Reply via email to