diff --git a/README.md b/README.md index 06abf42..588b5be 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,8 @@ because I don't. ## Where to read it -To read: http://www.greghendershott.com/fear-of-macros +- [Multiple HTML files](http://www.greghendershott.com/fear-of-macros) +- [One big HTML file](http://www.greghendershott.com/fear-of-macros/all.html) ## Feeback diff --git a/Robust_macros__syntax-parse.html b/Robust_macros__syntax-parse.html index bac8e1c..959cd46 100644 --- a/Robust_macros__syntax-parse.html +++ b/Robust_macros__syntax-parse.html @@ -22,7 +22,7 @@ classes". There are predefined syntax classes, plus we can define our own.

7.3 Using syntax/parse

November 1, 2012: So here’s the deal. After writing everything up to this point, I sat down to re-read the documentation for syntax/parse. It was...very understandable. I didn’t feel -confused.

<span style='accent: "Kenau-Reeves"'>
Whoa.
</span>

Why? The documentation is written very well. Also, everything up to +confused.

<span style='accent: "Keanu-Reeves"'>
Whoa.
</span>

Why? The documentation is written very well. Also, everything up to this point prepared me to appreciate what syntax/parse does, and why. That leaves the "how" of using it, which seems pretty straightforward, so far.

This might well be a temporary state of me "not knowing what I don’t diff --git a/Syntax_parameters.html b/Syntax_parameters.html index dcc5573..adacb2d 100644 --- a/Syntax_parameters.html +++ b/Syntax_parameters.html @@ -10,9 +10,9 @@ Bindings, has a good explanation and example. Basically, syntax has "marks" to preserve lexical scope. This makes your macro behave like a normal function, for lexical scoping.

If a normal function defines a variable named x, it won’t conflict with a variable named x in an outer scope:

> (let ([x "outer"])
    (let ([x "inner"])
      (printf "The inner `x' is ~s\n" x))
    (printf "The outer `x' is ~s\n" x))

The inner `x' is "inner"

The outer `x' is "outer"

When our macros also respect lexical scoping, it’s easier to write -reliable macros that behave predictably.

So that’s wonderful default behavior. But sometimes we want -to introduce a magic variable on purpose—such as it for -aif.

The way to do this is with a "syntax parameter", using +reliable macros that behave predictably.

So that’s wonderful default behavior. But sometimes we want to +introduce a magic variable on purpose—such as it for +aif.

There’s a bad way to do this and a good way.

The bad way is to use datum->syntax, which is tricky to use correctly. See Keeping it Clean with Syntax Parameters (PDF).

The good way is with a syntax parameter, using define-syntax-parameter and syntax-parameterize. You’re probably familiar with regular parameters in Racket:

> (define current-foo (make-parameter "some default value"))
> (current-foo)

"some default value"

> (parameterize ([current-foo "I have a new value, for now"])
    (current-foo))

"I have a new value, for now"

> (current-foo)

"some default value"

That’s a normal parameter. The syntax variation works similarly. The diff --git a/Transform_.html b/Transform_.html index 8929b93..48cb66e 100644 --- a/Transform_.html +++ b/Transform_.html @@ -17,8 +17,8 @@ string literal. How about returning ((say-hi), and sees it has a transformer function for that. It calls our function with the old syntax, and we return the new syntax, which is used to evaluate and run our program.

3.2 What’s the input?

Our examples so far have ignored the input syntax and output some -fixed syntax. But typically we will want to transform in the input -syntax into somehing else.

Let’s start by looking closely at what the input actually is:

> (define-syntax (show-me stx)
    (print stx)
    #'(void))
> (show-me '(+ 1 2))

#<syntax:10:0 (show-me (quote (+ 1 2)))>

The (print stx) shows what our transformer is given: a syntax +fixed syntax. But typically we will want to transform the input syntax +into something else.

Let’s start by looking closely at what the input actually is:

> (define-syntax (show-me stx)
    (print stx)
    #'(void))
> (show-me '(+ 1 2))

#<syntax:10:0 (show-me (quote (+ 1 2)))>

The (print stx) shows what our transformer is given: a syntax object.

A syntax object consists of several things. The first part is the S-expression representing the code, such as '(+ 1 2).

Racket syntax is also decorated with some interesting information such as the source file, line number, and column. Finally, it has diff --git a/all.html b/all.html index 33b6ba8..7bf69aa 100644 --- a/all.html +++ b/all.html @@ -1,6 +1,6 @@ Fear of Macros

1 Preface
2 Our plan of attack
3 Transform!
3.1 What is a syntax transformer?
3.2 What’s the input?
3.3 Actually transforming the input
3.4 Compile time vs. run time
3.5 begin-for-syntax
4 Pattern matching:   syntax-case and syntax-rules
4.1 Pattern variable vs. template—fight!
4.1.1 with-syntax
4.1.2 with-syntax*
4.1.3 format-id
4.1.4 Another example
4.2 Making our own struct
4.3 Using dot notation for nested hash lookups
5 Syntax parameters
6 What’s the point of splicing-let?
7 Robust macros:   syntax-parse
7.1 Error-handling strategies for functions
7.2 Error-handling strategies for macros
7.3 Using syntax/  parse
8 References and Acknowledgments
9 Epilogue

Fear of Macros

-
Copyright (c) 2012-2013 by Greg Hendershott. All rights reserved.
Last updated 2013-08-15T13:36:35
Feedback and corrections are welcome here.

Contents:

    1 Preface

    2 Our plan of attack

    3 Transform!

      3.1 What is a syntax transformer?

      3.2 What’s the input?

      3.3 Actually transforming the input

      3.4 Compile time vs. run time

      3.5 begin-for-syntax

    4 Pattern matching: syntax-case and syntax-rules

      4.1 Pattern variable vs. template—fight!

        4.1.1 with-syntax

        4.1.2 with-syntax*

        4.1.3 format-id

        4.1.4 Another example

      4.2 Making our own struct

      4.3 Using dot notation for nested hash lookups

    5 Syntax parameters

    6 What’s the point of splicing-let?

    7 Robust macros: syntax-parse

      7.1 Error-handling strategies for functions

      7.2 Error-handling strategies for macros

      7.3 Using syntax/parse

    8 References and Acknowledgments

    9 Epilogue

1 Preface

I learned Racket after 25 years of mostly using C and C++.

Some psychic whiplash resulted.

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

Copyright (c) 2012-2013 by Greg Hendershott. All rights reserved.
Last updated 2013-08-15T14:15:12
Feedback and corrections are welcome here.

Contents:

    1 Preface

    2 Our plan of attack

    3 Transform!

      3.1 What is a syntax transformer?

      3.2 What’s the input?

      3.3 Actually transforming the input

      3.4 Compile time vs. run time

      3.5 begin-for-syntax

    4 Pattern matching: syntax-case and syntax-rules

      4.1 Pattern variable vs. template—fight!

        4.1.1 with-syntax

        4.1.2 with-syntax*

        4.1.3 format-id

        4.1.4 Another example

      4.2 Making our own struct

      4.3 Using dot notation for nested hash lookups

    5 Syntax parameters

    6 What’s the point of splicing-let?

    7 Robust macros: syntax-parse

      7.1 Error-handling strategies for functions

      7.2 Error-handling strategies for macros

      7.3 Using syntax/parse

    8 References and Acknowledgments

    9 Epilogue

1 Preface

I learned Racket after 25 years of mostly using C and C++.

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 @@ -60,8 +60,8 @@ string literal. How about returning ((say-hi), and sees it has a transformer function for that. It calls our function with the old syntax, and we return the new syntax, which is used to evaluate and run our program.

3.2 What’s the input?

Our examples so far have ignored the input syntax and output some -fixed syntax. But typically we will want to transform in the input -syntax into somehing else.

Let’s start by looking closely at what the input actually is:

> (define-syntax (show-me stx)
    (print stx)
    #'(void))
> (show-me '(+ 1 2))

#<syntax:10:0 (show-me (quote (+ 1 2)))>

The (print stx) shows what our transformer is given: a syntax +fixed syntax. But typically we will want to transform the input syntax +into something else.

Let’s start by looking closely at what the input actually is:

> (define-syntax (show-me stx)
    (print stx)
    #'(void))
> (show-me '(+ 1 2))

#<syntax:10:0 (show-me (quote (+ 1 2)))>

The (print stx) shows what our transformer is given: a syntax object.

A syntax object consists of several things. The first part is the S-expression representing the code, such as '(+ 1 2).

Racket syntax is also decorated with some interesting information such as the source file, line number, and column. Finally, it has @@ -272,9 +272,9 @@ Bindings, has a good explanation and example. Basically, syntax has "marks" to preserve lexical scope. This makes your macro behave like a normal function, for lexical scoping.

If a normal function defines a variable named x, it won’t conflict with a variable named x in an outer scope:

> (let ([x "outer"])
    (let ([x "inner"])
      (printf "The inner `x' is ~s\n" x))
    (printf "The outer `x' is ~s\n" x))

The inner `x' is "inner"

The outer `x' is "outer"

When our macros also respect lexical scoping, it’s easier to write -reliable macros that behave predictably.

So that’s wonderful default behavior. But sometimes we want -to introduce a magic variable on purpose—such as it for -aif.

The way to do this is with a "syntax parameter", using +reliable macros that behave predictably.

So that’s wonderful default behavior. But sometimes we want to +introduce a magic variable on purpose—such as it for +aif.

There’s a bad way to do this and a good way.

The bad way is to use datum->syntax, which is tricky to use correctly. See Keeping it Clean with Syntax Parameters (PDF).

The good way is with a syntax parameter, using define-syntax-parameter and syntax-parameterize. You’re probably familiar with regular parameters in Racket:

> (define current-foo (make-parameter "some default value"))
> (current-foo)

"some default value"

> (parameterize ([current-foo "I have a new value, for now"])
    (current-foo))

"I have a new value, for now"

> (current-foo)

"some default value"

That’s a normal parameter. The syntax variation works similarly. The @@ -316,7 +316,7 @@ classes". There are predefined syntax classes, plus we can define our own.

7.3 Using syntax/parse

November 1, 2012: So here’s the deal. After writing everything up to this point, I sat down to re-read the documentation for syntax/parse. It was...very understandable. I didn’t feel -confused.

<span style='accent: "Kenau-Reeves"'>
Whoa.
</span>

Why? The documentation is written very well. Also, everything up to +confused.

<span style='accent: "Keanu-Reeves"'>
Whoa.
</span>

Why? The documentation is written very well. Also, everything up to this point prepared me to appreciate what syntax/parse does, and why. That leaves the "how" of using it, which seems pretty straightforward, so far.

This might well be a temporary state of me "not knowing what I don’t diff --git a/index.html b/index.html index a0f4e45..a4da1b7 100644 --- a/index.html +++ b/index.html @@ -1,3 +1,3 @@ Fear of Macros

Fear of Macros

-
Copyright (c) 2012-2013 by Greg Hendershott. All rights reserved.
Last updated 2013-08-15T13:36:30
Feedback and corrections are welcome here.

Contents:

    1 Preface

    2 Our plan of attack

    3 Transform!

      3.1 What is a syntax transformer?

      3.2 What’s the input?

      3.3 Actually transforming the input

      3.4 Compile time vs. run time

      3.5 begin-for-syntax

    4 Pattern matching: syntax-case and syntax-rules

      4.1 Pattern variable vs. template—fight!

        4.1.1 with-syntax

        4.1.2 with-syntax*

        4.1.3 format-id

        4.1.4 Another example

      4.2 Making our own struct

      4.3 Using dot notation for nested hash lookups

    5 Syntax parameters

    6 What’s the point of splicing-let?

    7 Robust macros: syntax-parse

      7.1 Error-handling strategies for functions

      7.2 Error-handling strategies for macros

      7.3 Using syntax/parse

    8 References and Acknowledgments

    9 Epilogue

 
\ No newline at end of file +
Copyright (c) 2012-2013 by Greg Hendershott. All rights reserved.
Last updated 2013-08-15T14:15:07
Feedback and corrections are welcome here.

Contents:

    1 Preface

    2 Our plan of attack

    3 Transform!

      3.1 What is a syntax transformer?

      3.2 What’s the input?

      3.3 Actually transforming the input

      3.4 Compile time vs. run time

      3.5 begin-for-syntax

    4 Pattern matching: syntax-case and syntax-rules

      4.1 Pattern variable vs. template—fight!

        4.1.1 with-syntax

        4.1.2 with-syntax*

        4.1.3 format-id

        4.1.4 Another example

      4.2 Making our own struct

      4.3 Using dot notation for nested hash lookups

    5 Syntax parameters

    6 What’s the point of splicing-let?

    7 Robust macros: syntax-parse

      7.1 Error-handling strategies for functions

      7.2 Error-handling strategies for macros

      7.3 Using syntax/parse

    8 References and Acknowledgments

    9 Epilogue

 
\ No newline at end of file diff --git a/index.rkt b/index.rkt index c5c4608..904c82e 100644 --- a/index.rkt +++ b/index.rkt @@ -234,8 +234,8 @@ which is used to evaluate and run our program. @subsection{What's the input?} Our examples so far have ignored the input syntax and output some -fixed syntax. But typically we will want to transform in the input -syntax into somehing else. +fixed syntax. But typically we will want to transform the input syntax +into something else. Let's start by looking closely at what the input actually @italic{is}: @@ -1305,11 +1305,15 @@ conflict with a variable named @racket[x] in an outer scope: When our macros also respect lexical scoping, it's easier to write reliable macros that behave predictably. -So that's wonderful default behavior. But @italic{sometimes} we want -to introduce a magic variable on purpose---such as @racket[it] for +So that's wonderful default behavior. But sometimes we want to +introduce a magic variable on purpose---such as @racket[it] for @racket[aif]. -The way to do this is with a "syntax parameter", using +There's a bad way to do this and a good way. + +The bad way is to use @racket[datum->syntax], which is tricky to use correctly. @margin-note*{See @hyperlink["http://www.schemeworkshop.org/2011/papers/Barzilay2011.pdf" "Keeping it Clean with Syntax Parameters (PDF)"].} + +The good way is with a syntax parameter, using @racket[define-syntax-parameter] and @racket[syntax-parameterize]. You're probably familiar with regular parameters in Racket: @@ -1558,7 +1562,7 @@ this point, I sat down to re-read the documentation for confused. @codeblock{ - + Whoa. }