(I asked these questions on #clojure, and the friendly locals
suggested I open the question up for a wider audience.)

I'm trying to write a macro-writing-macro. My code has a bunch of
resources which have -open and -close type of calls, and they could
all benefit from with- wrappers. The with- wrappers all have similar
structure, and I thought I would be better off defining them with
another macro:

(defmacro def-with-db-macro [macro-name open-fn close-fn]
  `(defmacro ~macro-name [[var# & open-args#] & body#]
     `(let [~var# (apply ~'~open-fn [...@open-args#])]
        (try
         ~...@body#
         (finally (~'~close-fn ~var#))))))

Sample use:

(def-with-db-macro with-db-env db-env-open db-env-close)

(def-with-db-macro with-db db-open db-close)

(def-with-db-macro with-db-txn db-txn-begin
  (fn [txn] (when (= @(txn :status) :open) (db-txn-commit txn))))

This mostly works. It breaks if I try using, e.g., with-db-env in a
namespace which does not import db-env-open or db-env-close.

Chris Houser has summarized the problem here more succinctly than I
can: http://paste.lisp.org/display/87734

While searching for a workaround, I thought maybe I could capture the
functions I need during expansion of def-with-db-macro, but kept
getting a useless exception. I ended up reducing that problem to this:

(let [f1 #(inc %)]
  (defmacro m1 [x]
    `(~f1 ~x)))

(m1 12)
=> No message.
  [Thrown class java.lang.ExceptionInInitializerError]

The equivalent works in Common Lisp (Allegro CL and SBCL):

(let ((f1 (lambda (y) (1+ y))))
  (defmacro m1 (x)
    `(funcall ,f1 ,x)))

(m1 12)
=> 13

Thoughts on either of these brain teasers?

Thanks!

PS: To read the IRC discussion, see 
http://clojure-log.n01se.net/date/2009-09-25.html
and scroll down to the discussion starting at 15:16.
--~--~---------~--~----~------------~-------~--~----~
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