7

What is the best route for an experienced imperative style programmer only familiar with C macros to learn the Racket macro system. Not just the mechanics of it (the how?) but also the where and why to use it and examples that illustrate this.

Should one learn Scheme (or Lisp) macros first? I've heard that the book "On Lisp" has a good explanation of Lisp macros with excellent examples of their use. Would this be useful or not?

Harry Spier
  • 1,395
  • 16
  • 30

2 Answers2

12

I believe that the best tutorial on macros is still Kent Dybvig's "Writing Hygenic macros in Scheme with syntax-case". It's not specifically about Racket, but basically everything will carry over, and reading the guide that Chris mentioned above will cover any remaining differences. Despite the name, it covers both "hygenic" and "unhygenic" macros.

Edit July 2014:

Since I wrote the above, Greg Hendershott has written a fabulous tutorial on macros in Racket, entitled Fear of Macros. That's now the best place to start learning about Racket macros.

Sam Tobin-Hochstadt
  • 4,983
  • 1
  • 21
  • 43
  • 2
    +1 for Dybvig's article. I've actually read it a while ago and it helped me understand `syntax-case` macros a lot, especially how things like `with-syntax` worked. – C. K. Young Nov 05 '11 at 05:45
5

Racket's documentation has an excellent tutorial on using macros.

I would definitely recommend Scheme macros over CL macros if you haven't deal with any sort of Lisp macros before. That's because Scheme macros use pattern matching, and it's much easier to read.

Example (using Racket's define-syntax-rule):

(define-syntax-rule (let ((var val) ...)
                      expr ...)
  ((lambda (var ...)
     expr ...)
   val ...))

This is a very simple macro that defines let in terms of creating a corresponding lambda, then applying it. It's easy to read, and easy to reason about what it does.

Slightly more complicated macro:

(define-syntax let*
  (syntax-rules ()
    ((let* ()
       expr ...)
     (let ()
       expr ...))
    ((let* ((var val) next ...)
       expr ...)
     (let ((var val))
       (let* (next ...)
         expr ...)))))

This defines let* in terms of nested lets, so that the bindings are done sequentially. It includes a base case (with no bindings), as well as a recursive case.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • Can you recommend any books for this. – Harry Spier Nov 03 '11 at 13:37
  • 1
    Don't know about books, but Racket has an excellent guide for macros: http://docs.racket-lang.org/guide/macros.html – C. K. Young Nov 03 '11 at 13:39
  • You should update the answer with this pointer, since it's a more direct answer to the original question... – Eli Barzilay Nov 03 '11 at 18:18
  • 2
    I have just found Ryan Culpepper's dissertation: "Refining Syntactic Sugar: Tools for Supporting Macro Development" with the case studies in chapter 8. http://www.ccs.neu.edu/scheme/pubs/dissertation-culpepper.pdf – Harry Spier Nov 04 '11 at 00:33