3 ms·
The Underbelly of Racket Macro Basics
- idoh 13y agoI've been trying to learn Racket macros but articles like this make me feel like I should just give up. For example, in arc a macro looks like this: (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.
- gnaritas 13y ago> 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.
- mordae 13y agoYour code (`when` that binds `it`) translates to: (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?
- kogir 13y agoIf you're trying to get things done in Racket, just learn define-syntax-rule [1] and syntax/parse [2]. 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.html
- jeapostrophe 13y agoThis is Jay. Arc macros are like define-syntax-rule macros in Racket. dsr is great for lots of things, but sometimes you need more power. In 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.
- gtani 13y agoI just noticed Realm of Racket in my local bookstore a few days ago. Haven't had time to peruse, but looks good, a dozen pages on macros http://nostarch.com/realmofracket 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/005417.html http://mail.openjdk.java.net/pipermail/mlvm-dev/2013-July/00...