Various small edits.

This commit is contained in:
Greg Hendershott 2012-11-01 23:01:11 -04:00
parent ab6ca8cd39
commit e918444b48

View File

@ -79,7 +79,7 @@ understand the answers and solutions.
@; ---------------------------------------------------------------------------- @; ----------------------------------------------------------------------------
@section{The plan of attack} @section{Our plan of attack}
The macro system you will mostly want to use for production-quality The macro system you will mostly want to use for production-quality
macros is called @racket[syntax-parse]. And don't worry, we'll get to macros is called @racket[syntax-parse]. And don't worry, we'll get to
@ -89,10 +89,10 @@ But if we start there, you're likely to feel overwhelmed by concepts
and terminology, and get very confused. I did. and terminology, and get very confused. I did.
1. Instead let's start with the basics: A syntax object and a function 1. Instead let's start with the basics: A syntax object and a function
to change it (a "transformer"). We'll work at that level for awhile to to change it---a "transformer". We'll work at that level for awhile to
get comfortable and to de-mythologize this whole macro business. get comfortable and to de-mythologize this whole macro business.
2. Next, we'll realize that some pattern-matching would make life 2. Soon we'll realize that pattern-matching would make life
easier. We'll learn about @racket[syntax-case] and its shorthand easier. We'll learn about @racket[syntax-case] and its shorthand
cousin, @racket[define-syntax-rule]. We'll discover we can get cousin, @racket[define-syntax-rule]. We'll discover we can get
confused if we want to munge pattern variables before sticking them confused if we want to munge pattern variables before sticking them
@ -117,7 +117,7 @@ enhancements is @racket[syntax-parse].
@; ---------------------------------------------------------------------------- @; ----------------------------------------------------------------------------
@; ---------------------------------------------------------------------------- @; ----------------------------------------------------------------------------
@section{Transformers} @section{Transform!}
@verbatim[#:indent 2]{ @verbatim[#:indent 2]{
YOU ARE INSIDE A ROOM. YOU ARE INSIDE A ROOM.
@ -227,9 +227,9 @@ which is used to evaluate and run our program.
@subsection{What's the input?} @subsection{What's the input?}
Our examples so far ignored the input syntax, and output a fixed Our examples so far have ignored the input syntax and output some
syntax. But instead of throwing away the input, usually we want to fixed syntax. But typically we will want to transform in the input
transform the input. syntax into somehing else.
Let's start by looking closely at what the input actually @italic{is}: Let's start by looking closely at what the input actually @italic{is}:
@ -244,7 +244,7 @@ The @racket[(print stx)] shows what our transformer is given: a syntax
object. object.
A syntax object consists of several things. The first part is the A syntax object consists of several things. The first part is the
s-expression representing the code, such as @racket['(+ 1 2)]. S-expression representing the code, such as @racket['(+ 1 2)].
Racket syntax is also decorated with some interesting information such Racket syntax is also decorated with some interesting information such
as the source file, line number, and column. Finally, it has as the source file, line number, and column. Finally, it has
@ -260,7 +260,7 @@ stx
] ]
Now let's use functions that access the syntax object. The source Now let's use functions that access the syntax object. The source
information functions: information functions are:
@margin-note{@racket[(syntax-source stx)] is returning @racket['eval], @margin-note{@racket[(syntax-source stx)] is returning @racket['eval],
only becaue of how I'm generating this documentation, using an only becaue of how I'm generating this documentation, using an
@ -274,7 +274,7 @@ somthing like "my-file.rkt".}
] ]
More interesting is the syntax "stuff" itself. @racket[syntax->datum] More interesting is the syntax "stuff" itself. @racket[syntax->datum]
converts it completely into an s-expression: converts it completely into an S-expression:
@i[ @i[
(syntax->datum stx) (syntax->datum stx)
@ -297,9 +297,8 @@ In most cases, @racket[syntax->list] gives the same result as
(syntax->list stx) (syntax->list stx)
] ]
When would @racket[syntax-e] and @racket[syntax->list] differ? Let's (When would @racket[syntax-e] and @racket[syntax->list] differ? Let's
not get side-tracked now. not get side-tracked now.)
When we want to transform syntax, we'll generally take the pieces we When we want to transform syntax, we'll generally take the pieces we
were given, maybe rearrange their order, perhaps change some of the were given, maybe rearrange their order, perhaps change some of the
@ -356,9 +355,9 @@ compiler, and @italic{that} syntax is evaluated:
@subsection{Compile time vs. run time} @subsection{Compile time vs. run time}
@codeblock[#:indent 10]{ @codeblock0{
(define-syntax (foo stx) (define-syntax (foo stx)
(make-pipe) ;This is not run time. (make-pipe) ;Ce n'est pas le temps d'exécution
#'(void)) #'(void))
} }
@ -520,6 +519,8 @@ So let's try that:
(our-if-using-match-v2 #t "true" "false") (our-if-using-match-v2 #t "true" "false")
] ]
Joy.
@; ---------------------------------------------------------------------------- @; ----------------------------------------------------------------------------
@subsection{@racket[begin-for-syntax]} @subsection{@racket[begin-for-syntax]}
@ -569,7 +570,7 @@ syntax without evaluating them. We can implement forms like
@item{More good news is that there isn't some special, weird language @item{More good news is that there isn't some special, weird language
for writing syntax transformers. We can write these transformer for writing syntax transformers. We can write these transformer
functions using the Racket language we already know and lovex.} functions using the Racket language we already know and love.}
@item{The semi-bad news is that the familiarity can make it easy to forget @item{The semi-bad news is that the familiarity can make it easy to forget
that we're not working at run time. Sometimes that's important to that we're not working at run time. Sometimes that's important to
@ -671,7 +672,7 @@ working.
@; ---------------------------------------------------------------------------- @; ----------------------------------------------------------------------------
@subsection{"A pattern variable can't be used outside of a template"} @subsection{Pattern variable vs. template---fight!}
Let's say we want to define a function with a hyphenated name, a-b, Let's say we want to define a function with a hyphenated name, a-b,
but we supply the a and b parts separately. The Racket @racket[struct] but we supply the a and b parts separately. The Racket @racket[struct]
@ -754,13 +755,13 @@ Well that explains it. Instead, we wanted to expand to:
Our template is using the symbol @racket[name] but we wanted its Our template is using the symbol @racket[name] but we wanted its
value, such as @racket[foo-bar] in this use of our macro. value, such as @racket[foo-bar] in this use of our macro.
Can we think of something we already know that behaves like Is there anything we already know that behaves like this---where using
this---where using a variable in the template yields its value? Sure a variable in the template yields its value? Yes: Pattern
we do: Pattern variables. Our pattern doesn't include @racket[name] variables. Our pattern doesn't include @racket[name] because we don't
because we don't expect it in the original syntax---indeed the whole expect it in the original syntax---indeed the whole point of this
point of this macro is to create it. So @racket[name] can't be in the macro is to create it. So @racket[name] can't be in the main
main pattern. Fine---let's make an @italic{additional} pattern. We can pattern. Fine---let's make an @italic{additional} pattern. We can do
do that using an additional, nested @racket[syntax-case]: that using an additional, nested @racket[syntax-case]:
@i[ @i[
(define-syntax (hyphen-define/wrong1.2 stx) (define-syntax (hyphen-define/wrong1.2 stx)
@ -829,7 +830,7 @@ And now it works!
Now for two shortcuts. Now for two shortcuts.
Instead of an additional, nested @racket[syntax-case] we could use Instead of an additional, nested @racket[syntax-case], we could use
@racket[with-syntax]@margin-note*{Another name for @racket[with-syntax]@margin-note*{Another name for
@racket[with-syntax] could be, "define pattern variable".}. This @racket[with-syntax] could be, "define pattern variable".}. This
rearranges the @racket[syntax-case] to look more like a @racket[let] rearranges the @racket[syntax-case] to look more like a @racket[let]
@ -901,7 +902,7 @@ To review:
@item{You can't use a pattern variable outside of a template. But @item{You can't use a pattern variable outside of a template. But
you can use @racket[syntax] or @tt{#'} on a pattern variable to make you can use @racket[syntax] or @tt{#'} on a pattern variable to make
an ad hoc "fun size" template.} an ad hoc, "fun size" template.}
@item{If you want to munge pattern variables for use in the @item{If you want to munge pattern variables for use in the
template, @racket[with-syntax] is your friend, because it lets you template, @racket[with-syntax] is your friend, because it lets you
@ -1057,9 +1058,15 @@ pieces.
If you write programs for web services you deal with JSON, which is If you write programs for web services you deal with JSON, which is
represented in Racket by a @racket[jsexpr?]. JSON often has represented in Racket by a @racket[jsexpr?]. JSON often has
dictionaries that contain other dictionaries. In a @racket[jsexpr?] dictionaries that contain other dictionaries. In a @racket[jsexpr?]
these are represented by nested @racket[hasheq] tables. these are represented by nested @racket[hasheq] tables:
JavaScript you can use dot notation: @#reader scribble/comment-reader
(i
; Nested `hasheq's typical of a jsexpr:
(define js (hasheq 'a (hasheq 'b (hasheq 'c "value"))))
)
In JavaScript you can use dot notation:
@codeblock{ @codeblock{
foo = js.a.b.c; foo = js.a.b.c;
@ -1067,13 +1074,7 @@ foo = js.a.b.c;
In Racket it's not so convenient: In Racket it's not so convenient:
@#reader scribble/comment-reader @racketblock[(hash-ref (hash-ref (hash-ref js 'a) 'b) 'c)]
(i
; Nested hasheqs typical of a jsexpr:
(define js (hasheq 'a (hasheq 'b (hasheq 'c "value"))))
; Typical annoying code to get something:
(hash-ref (hash-ref (hash-ref js 'a) 'b) 'c)
)
We can write a helper function to make this a bit cleaner: We can write a helper function to make this a bit cleaner:
@ -1092,7 +1093,7 @@ We can write a helper function to make this a bit cleaner:
(hash-refs js '(a b c)) (hash-refs js '(a b c))
) )
That's not bad. Can we go even further and use a dot notation somewhat That's better. Can we go even further and use a dot notation somewhat
like JavaScript? like JavaScript?
@#reader scribble/comment-reader @#reader scribble/comment-reader