The Underbelly of Racket Macro Basics
jeapostrophe.github.io
jeapostrophe.github.io
(mac awhen (expr . body)
`(let it ,expr (if it (do ,@body))))
I can understand that, and start making macros and going about my business. The Racket guys (e.g. Eli and Jay) write macros that look like this: (require (lib "stxparam.ss" "mzlib"))
(define-syntax-parameter it
(lambda (stx)
(raise-syntax-error #f "can only be used inside `if'" stx)))
(define-syntax if*
(syntax-rules ()
[(if*) (void)]
[(if* X) X]
[(if* C X more ...)
(let ([b C])
(if b
(syntax-parameterize ([it (make-rename-transformer #'b)]) X)
(if* more ...)))]))
Or like this: (define-syntax (123-list stx)
(define middle-x-stx (second (syntax->list stx)))
(define x-id (syntax-e middle-x-stx))
(define new-ctxt-stx (datum->syntax #f 'new-ctxt))
(datum->syntax
new-ctxt-stx
(list (datum->syntax #'123-list 'let)
(list (list x-id (datum->syntax #'123-list 3)))
(list (datum->syntax #'123-list '#%app)
(datum->syntax #'123-list 'list)
(datum->syntax #'123-list x-id)
middle-x-stx
x-id))))
They have reasonable objections to arc-style macros, but I feel like they are overly academic and not relevant to the programming problems that I want to address. I want to eliminate boilerplate, and I'm willing to take the limitations of arc-style macros because they are so much easier to understand.Then don't use scheme, hygienic macros has always been a major difference between a scheme and a lisp.
(define-syntax (awhen stx)
(syntax-case stx ()
((_ expr body ...)
(with-syntax ((it (datum->syntax stx 'it)))
#`(let ((it expr))
(when it body ...))))))
I find it a bit hairy, but mostly sane. It's all about being hygienic. Notice how you explicitly place the `it` identifier into the caller's context but keep the usual let and when?You also picked as your example the one thing unhygienic macros are good at. Even in arc.arc, most macros start with (w/uniq (let boilerplate like:
(mac or args
(and args
(w/uniq g
`(let ,g ,(car args)
(if ,g ,g (or ,@(cdr args)))))))
In my code breaking hygiene is the exception, not the common case, and my Racket macros are usually shorter than the equivalent arc macros. [1]: http://docs.racket-lang.org/guide/pattern-macros.html
[2]: http://docs.racket-lang.org/syntax/stxparse.htmlIn any case, this post is really about what's going on in the pattern matching and macro template underbelly, and not really a recommendation for how to program macros.
http://nostarch.com/realmofracket (download a chapter, index and ToC)
_______________________________________
also, on the openJDK list, they're looking at Clements/Felleisen's tail call writeup from 2004
http://mail.openjdk.java.net/pipermail/mlvm-dev/2013-July/00...