TL;DR I have an extra clojure.core/fn wrapped around the form I want
returned from my macro. This is my first macro and I'm not sure what's
wrong, even though the macro "works."

I'm trying my first attempt at a macro by trying to save myself from
having to type "sql/with-connection db" for every time I want to
invoke a database command. I figure I can type "dc" (short for
"database connection") instead.

I'm doing something wrong but I've tried a few iterations of ', `, ~,
and ~@ the closest I got was this one:

(def db {:classname "org.postgresql.Driver"
         :subprotocol "postgresql"
         :subname (str "//localhost:5432/shouter")
         :user "username"
         :password "1234"})

(defmacro dc
  [sql-cmd]
  (list 'sql/with-connection 'db
        sql-cmd))

This macro works in that it actually invokes the form I want, but when
I run macroexpand on it I have an extra clojure.core/fn wrapped around
my command, and when I compare that output to the "when" macro (which
does not have the clojure.core/fn wrapper that I can see), I think
I've got it wrong.

user> (macroexpand '(when (pos? a) (println "positive") (/ b a)))
(if (pos? a) (do (println "positive") (/ b a)))

user> (macroexpand '(dc (sql/create-table :testing [:data :text])))
(clojure.java.jdbc.internal/with-connection* db (clojure.core/fn []
(sql/create-table :testing [:data :text])))

I've also tried it with "& args" so I don't have to put my
"sql/create-table ..." form in parens, but it seems to work even worse
(I've still got the extra clojure.core/fn and now parens are around
the args).

(defmacro dc1
  [sql-cmd & args]
  (list 'sql/with-connection 'db
        sql-cmd args))

user> (macroexpand '(dc1 sql/create-table :testing [:data :text]))
(clojure.java.jdbc.internal/with-connection* db (clojure.core/fn []
sql/create-table (:testing [:data :text])))

I also tried this variation, which works but instead of returning the
status of the database command (0) as dc did, it returns the last arg
passed in, [:data :text].

(defmacro dc2
  [sql-cmd & args]
  `(sql/with-connection db
        ~sql-cmd ~@args))

user> (macroexpand '(dc2 sql/create-table :testing [:data :text]))
(clojure.java.jdbc.internal/with-connection* user/db (clojure.core/fn
[] sql/create-table :testing [:data :text]))

Any ideas on where I'm specifically going wrong, or where to read
further on macros (preferably simple examples)?

Thanks,
Peter

-- 
The king’s heart is like a stream of water directed by the Lord; He
guides it wherever He pleases.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to