diff --git a/References_and_Acknowledgments.html b/References_and_Acknowledgments.html index 515d7a2..fca391e 100644 --- a/References_and_Acknowledgments.html +++ b/References_and_Acknowledgments.html @@ -1,5 +1,5 @@ -8 References and Acknowledgments

8 References and Acknowledgments

Eli Barzliay’s blog post, +8 References and Acknowledgments

8 References and Acknowledgments

Eli Barzilay’s blog post, Writing ‘syntax-case’ Macros, helped me understand many key details and concepts, and inspired me to use a "bottom-up" approach.

Eli wrote another blog post, diff --git a/Transform_.html b/Transform_.html index c30970d..68c9f42 100644 --- a/Transform_.html +++ b/Transform_.html @@ -26,7 +26,7 @@ information about lexical scoping (which you don’t need to worry about now, but will turn out to be important later.)

There are a variety of functions available to access a syntax object. Let’s define a piece of syntax:

> (define stx #'(if x (list "true") #f))
> stx

#<syntax:11:0 (if x (list "true") #f)>

Now let’s use functions that access the syntax object. The source information functions are:

(syntax-source stx) is returning 'eval, -only becaue of how I’m generating this documentation, using an +only because of how I’m generating this documentation, using an evaluator to run code snippets in Scribble. Normally this would be something like "my-file.rkt".

> (syntax-source stx)

'eval

> (syntax-line stx)

11

> (syntax-column stx)

0

More interesting is the syntax "stuff" itself. syntax->datum converts it completely into an S-expression:

> (syntax->datum stx)

'(if x (list "true") #f)

Whereas syntax-e only goes "one level down". It may return a diff --git a/all.html b/all.html index 088180b..e0fc1d5 100644 --- a/all.html +++ b/all.html @@ -1,6 +1,6 @@ Fear of Macros

Fear of Macros

-
Copyright (c) 2012-2014 by Greg Hendershott. All rights reserved.
Last updated 2014-06-25T12:36:17
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-2014 by Greg Hendershott. All rights reserved.
Last updated 2014-07-11T08:56:11
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 @@ -69,7 +69,7 @@ information about lexical scoping (which you don’t need to worry about now, but will turn out to be important later.)

There are a variety of functions available to access a syntax object. Let’s define a piece of syntax:

> (define stx #'(if x (list "true") #f))
> stx

#<syntax:11:0 (if x (list "true") #f)>

Now let’s use functions that access the syntax object. The source information functions are:

(syntax-source stx) is returning 'eval, -only becaue of how I’m generating this documentation, using an +only because of how I’m generating this documentation, using an evaluator to run code snippets in Scribble. Normally this would be something like "my-file.rkt".

> (syntax-source stx)

'eval

> (syntax-line stx)

11

> (syntax-column stx)

0

More interesting is the syntax "stuff" itself. syntax->datum converts it completely into an S-expression:

> (syntax->datum stx)

'(if x (list "true") #f)

Whereas syntax-e only goes "one level down". It may return a @@ -228,7 +228,7 @@ message:

...: ellipses format-id that lets us format identifier names more succinctly than what we did above:

> (require (for-syntax racket/syntax))
> (define-syntax (hyphen-define/ok3 stx)
    (syntax-case stx ()
      [(_ a b (args ...) body0 body ...)
       (with-syntax ([name (format-id stx "~a-~a" #'a #'b)])
         #'(define (name args ...)
             body0 body ...))]))
> (hyphen-define/ok3 bar baz () #t)
> (bar-baz)

#t

Using format-id is convenient as it handles the tedium of converting from syntax to symbol datum to string ... and all the way -back.

4.1.4 Another example

Finally, here’s a variation that accepts an arbitary number of name +back.

4.1.4 Another example

Finally, here’s a variation that accepts an arbitrary number of name parts to be joined with hyphens:

> (require (for-syntax racket/string racket/syntax))
> (define-syntax (hyphen-define* stx)
    (syntax-case stx ()
      [(_ (names ...) (args ...) body0 body ...)
       (let* ([names/sym (map syntax-e (syntax->list #'(names ...)))]
              [names/str (map symbol->string names/sym)]
              [name/str (string-join names/str "-")]
              [name/sym (string->symbol name/str)])
         (with-syntax ([name (datum->syntax stx name/sym)])
           #`(define (name args ...)
               body0 body ...)))]))
> (hyphen-define* (foo bar baz) (v) (* 2 v))
> (foo-bar-baz 50)

100

To review:

Copyright (c) 2012-2014 by Greg Hendershott. All rights reserved.
Last updated 2014-07-11T08:56:17
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/pattern-matching.html b/pattern-matching.html index b8f7a15..f3897ec 100644 --- a/pattern-matching.html +++ b/pattern-matching.html @@ -83,7 +83,7 @@ message:

...: ellipses format-id that lets us format identifier names more succinctly than what we did above:

> (require (for-syntax racket/syntax))
> (define-syntax (hyphen-define/ok3 stx)
    (syntax-case stx ()
      [(_ a b (args ...) body0 body ...)
       (with-syntax ([name (format-id stx "~a-~a" #'a #'b)])
         #'(define (name args ...)
             body0 body ...))]))
> (hyphen-define/ok3 bar baz () #t)
> (bar-baz)

#t

Using format-id is convenient as it handles the tedium of converting from syntax to symbol datum to string ... and all the way -back.

4.1.4 Another example

Finally, here’s a variation that accepts an arbitary number of name +back.

4.1.4 Another example

Finally, here’s a variation that accepts an arbitrary number of name parts to be joined with hyphens:

> (require (for-syntax racket/string racket/syntax))
> (define-syntax (hyphen-define* stx)
    (syntax-case stx ()
      [(_ (names ...) (args ...) body0 body ...)
       (let* ([names/sym (map syntax-e (syntax->list #'(names ...)))]
              [names/str (map symbol->string names/sym)]
              [name/str (string-join names/str "-")]
              [name/sym (string->symbol name/str)])
         (with-syntax ([name (datum->syntax stx name/sym)])
           #`(define (name args ...)
               body0 body ...)))]))
> (hyphen-define* (foo bar baz) (v) (* 2 v))
> (foo-bar-baz 50)

100

To review: