The ability to use macros to do code generation and transformation is
extremely useful. However, you still have to explicitly "call" the
macro everywhere you want it to be used. In many scenarios, it might
be desirable to do code transformation/generation on code, without
explicitly modifying that code to call the macro.

This could be accomplished by declaring a "meta-macro", which combines
a normal macro with a function which takes a form and tests whether
the macro ought to be applied. Then, somewhere in the compilation
pipeline, every form is passed to the test function, and the macro
applied if it returns true. Sort of like aspect-oriented programming
in Java.

For example, say I have a codebase that makes frequent calls to a
(sql ...) function to make a query to the database. I'm tracking down
an obscure performance bug, and I decide I want to log all calls to
(sql...), and time how long they took. But I don't want to modify the
sql function itself (it's in a third-party library), and it'd be a
major pain to find and replace all the hundreds of calls to it in my
codebase with a normal macro call, particularly as I'm going to want
to remove it all again after I finish my analysis. Enter metamacros:

(defmacro my-logger [sqlform]
   (do...)) ;standard macro body, wrapping a form with timing and
logging code.

(def-meta-macro log-sql
    (fn [form] (if (= sql (first form)))) ; test function
    my-logger) ; macro to apply

Recompile, and, poof. I've instrumented my entire program with
additional functionality in a handful of lines, without impact to my
existing codebase.

Of course, this would be tremendously susceptible to abuse, and if
used inappropriately could lead to some very, very hard-to-debug
errors. I'd think long and hard before using it in production code at
all (maybe even enable metamacros only with a specific compiler flag,
turned off by default?) But it's also very powerful, and allows one to
try new things across a codebase very easily. It's also incredibly
powerful... you could run it over a whole codebase to do static
analysis and transformations to improve performance, or to catch
stylistic errors. Hell, in theory, you could implement the entire
compiler just in metamacros ;)

Any thoughts? I grant you, the potential for abuse is huge. Would the
benefits outweigh it?

Thanks,
-Luke V.

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