[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Parodies make everyone mad

On Mon, 2002-11-18 at 13:31, Scott McKay wrote:
> This begs the question, what are a reasonable set of guidelines
> for writing good macros in a language like Lisp or Scheme.  Here
> are some rules of thumb I use; I'm embarrassed to write this
> because the shortness of the list and the lack of rigor shows
> the lack of depth in my thinking in this area.  I hope that
> people who've thought more deeply and thoroughly will use this
> as an excuse to write down a good list.

Well, I won't make any claims to having thought about these issues more
thoroughly than Scott McCay, but I'll chip in my two cents.

 1) Before writing a macro, create the best non-macro interface you
    can for the feature in question, then wrap a macro around it.
    This makes your macro much easier to write, and it allows you
    to access the underlying API in a more dynamic fashion if the
    need arises.  ("Oh, what a nice set of GUI macros!  But I want
    read my widget layouts from an XML file.  Drat.")

 2) Write small macros if they'd make your code cleaner.  ("Small",
    for the sake of discussion, means "anything you can do with
    syntax-rules and ten lines of code.")  If you follow rule (1)--
    and your macros are small enough--then your macros will be
    nearly as easy to grok as functions.  Even novice programmers
    can learn to do this right.

 3) Write big macros only under extreme provocation.  Big macros
    are dense, hard to maintain, and do alarming things to your
    language.  They're also invaluable, but you wouldn't want more
    than 10 of them per mid-sized company, or you'd go mad.  Even
    experts tend to make a pig's breakfast of big macros, so
    plan for extensive peer review.  And document each of them in
    your site's coding guidelines, OK?  (If you're Paul Graham,
    etc., certain exceptions may apply.)

Rules (2) and (3) are interesting--they suggest that there are two kinds
of macros.  I think is mirrored, to a certain extent, in Scheme's API,
where SYNTAX-RULES is (mostly) useful for defining small, inoffensive
macros and Chez Scheme's SYNTAX-CASE is (mostly) useful for defining
large, powerful, hard-to-maintain macros.

Neel's proposal to implement macros using an (object-oriented?) parse
tree interface is interesting here.  Combined with something like
SYNTAX-RULES, it would make the simple macros easy, and the hard macros
sufficiently difficult to scare away anyone without solid skills and a
pressing need. ;-) 

 4) Hygiene is good, because it allows you to preserve source
    location information and feed it to your IDE and debugger.
    Yes, SYNTAX-CASE is harder to use than LISP's
    DEFMACRO.  But doesn't DrScheme give such *nice* error
    messages when you use SYNTAX-CASE?  And isn't the automatic,
    accurate syntax highlighting pretty?

 5) Do not release a language (a) with macros and (b) without
    classes.  This will result in 60 incompatible macro
    libraries for implementing classes.  (The same goes for
    C++'s mysterious lack of a 'string' class until the STL
    appeared.)  If you have macros, make sure your language
    also includes all the constructs necessary for normal,
    modern programming styles.

 6) Do not, under any circumstance, write a LOOP or FOR macro
    that takes more than two pages of code to implement.  Nobody
    understands all the frobs and gadgets in Common LISP's LOOP,
    and few people use more than a third of Dylan's FOR macro.
    ("Oooh, in what order should we evaluate the test-clauses
    if we include *both* a frob-clause *and* a gadget-clause?")
    Adding massive amounts of chrome to core language features
    is pure self-indulgence.