diff --git a/index.html b/index.html index 2fff09c..9d0d78a 100644 --- a/index.html +++ b/index.html @@ -1,8 +1,8 @@ -Fear of Macros
1 Introduction
2 The plan of attack
3 Transformers
3.1 What is a syntax transformer?
3.2 What is the input?
3.3 Actually transforming the input
3.4 Compile time vs. run time
4 Pattern matching: syntax-case and syntax-rules
4.1 Patterns and templates
4.1.1 "A pattern variable can’t be used outside of a template"
5 Syntax parameters
6 Robust macros: syntax-parse
7 Other questions
7.1 What’s the point of with-syntax?
7.2 What’s the point of begin-for-syntax?
7.3 What’s the point of racket/ splicing?
8 References/ Acknowledgments
9 Epilogue

Fear of Macros

Greg Hendershott

+Fear of Macros

Fear of Macros

Copyright (c) 2012 by Greg Hendershott. All rights reserved. -
Last updated 2012-10-25 14:43:08

1 Introduction

I learned Racket after 25 years of doing C/C++ imperative programming.

Some psychic whiplash resulted.

"All the parentheses" was actually not a big deal. Instead, the first +

Last updated 2012-10-25 15:30:29

1 Introduction

I learned Racket after 25 years of doing C/C++ imperative programming.

Some psychic whiplash resulted.

"All the parentheses" was actually not a big deal. Instead, the first mind warp was functional programming. Before long I wrapped my brain around it, and went on to become comfortable and effective with many other aspects and features of Racket.

But two final frontiers remained: Macros and continuations.

I found that simple macros were easy and understandable, plus there @@ -12,7 +12,9 @@ terminology soup. I marinaded myself in material, hoping it would eventually sink in after enough re-readings. I even found myself using trial and error, rather than having a clear mental model what was going on. Gah.

I’m starting to write this at the point where the shapes are slowly -emerging from the fog.

My primary motive is selfish. Explaining something forces me to learn +emerging from the fog.

If you have any corrections, criticisms, complaints, or whatever, +please +let me know.

My primary motive is selfish. Explaining something forces me to learn it more thoroughly. Plus I expect that if I write something with mistakes, other people will be eager to point them out and correct me. Is that a social-engineering variation of meta-programming? Next @@ -167,9 +169,9 @@ it, it didn’t work. It seems that foo-bar didn’t get defined.

prefer to work in Emacs (like I do), in a situation like this it’s worth firing up DrRacket temporarily to use the Macro Stepper.

It shows us:

(module anonymous-module racket
  (#%module-begin
   (define-syntax (hyphen-define/wrong1.1 stx)
     (syntax-case stx ()
       [(_ a b (args ...) body0 body ...)
        (let ([name (string->symbol (format "~a-~a" #'a #'b))])
          #'(define (name args ...) body0 body ...))]))
   (define (name) #t)))

It shows that we’re expanding to (define (name) #t), but we wanted to expand to (define (foo-bar) #t).

So the problem is we’re getting name when we wanted its -value, foo-bar.

> (define-syntax (hyphen-define/wrong1.2 stx)
    (syntax-case stx ()
      [(_ a b (args ...) body0 body ...)
       (let ([name (string->symbol (format "~a-~a" #'a #'b))])
         #'(define (name args ...)
             body0 body ...))]))
> (hyphen-define/wrong1.2 foo bar () #t)
> (foo-bar)

foo-bar: undefined;

 cannot reference an identifier before its definition

  in module: 'program

The thing to reach for here is with-syntax. This will say -that name is in effect another pattern variable, and to use -its value:

> (define-syntax (hyphen-define/wrong1.3 stx)
    (syntax-case stx ()
      [(_ a b (args ...) body0 body ...)
       (with-syntax ([name (datum->syntax stx
                                          (string->symbol (format "~a-~a"
                                                                  #'a
                                                                  #'b)))])
         #'(define (name args ...)
             body0 body ...))]))
> (hyphen-define/wrong1.3 foo bar () #t)
> (foo-bar)

foo-bar: undefined;

 cannot reference an identifier before its definition

  in module: 'program

Hmm. foo-bar still not defined. Back to the Macro Stepper. It says we’re expanding to:

(define (|#<syntax:11:24foo>-#<syntax:11:28 bar>|) #t).

Ah, that’s right. #'a and #'b are syntax +value, foo-bar.

The thing to reach for here is with-syntax. This will say +that name is in effect another pattern variable, the value of +which we want to use in our main output template.

> (define-syntax (hyphen-define/wrong1.3 stx)
    (syntax-case stx ()
      [(_ a b (args ...) body0 body ...)
       (with-syntax ([name (datum->syntax stx
                                          (string->symbol (format "~a-~a"
                                                                  #'a
                                                                  #'b)))])
         #'(define (name args ...)
             body0 body ...))]))
> (hyphen-define/wrong1.3 foo bar () #t)
> (foo-bar)

foo-bar: undefined;

 cannot reference an identifier before its definition

  in module: 'program

Hmm. foo-bar still not defined. Back to the Macro Stepper. It says we’re expanding to:

(define (|#<syntax:11:24foo>-#<syntax:11:28 bar>|) #t).

Ah, that’s right. #'a and #'b are syntax objects. format is printing a representation of them as syntax objects. What we want is the datum inside the syntax object, the symbols foo and bar. So we should use diff --git a/main.rkt b/main.rkt index 88c8659..4757097 100644 --- a/main.rkt +++ b/main.rkt @@ -16,14 +16,14 @@ @image["fear-of-macros.jpg"] @title[#:version ""]{Fear of Macros} -@author{Greg Hendershott} +@author[@hyperlink["https://github.com/greghendershott/fear-of-macros/issues" + "Greg Hendershott"]] @smaller{Copyright (c) 2012 by Greg Hendershott. All rights reserved.} @para[@smaller["Last updated " (parameterize ([date-display-format 'iso-8601]) (date->string (current-date) #t))]] @table-of-contents{} - @; ---------------------------------------------------------------------------- @section{Introduction} @@ -50,6 +50,10 @@ going on. Gah. I'm starting to write this at the point where the shapes are slowly emerging from the fog. +@margin-note{If you have any corrections, criticisms, complaints, or whatever, +@hyperlink["https://github.com/greghendershott/fear-of-macros/issues" "please +let me know"].} + My primary motive is selfish. Explaining something forces me to learn it more thoroughly. Plus I expect that if I write something with mistakes, other people will be eager to point them out and correct