Fear of Macros

Contents:
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 +
Contents:
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
@@ -61,7 +61,7 @@ string literal. How about returning (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: #<syntax:10:0 (show-me (quote (i am a list)))> The (print stx) shows what our transformer is given: a syntax
+syntax into somehing else. Let’s start by looking closely at what the input actually is: #<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
@@ -168,8 +168,9 @@ transformer, and worked up from that, we won’t have that problem. We
can appreciate define-syntax-rule as a convenient shorthand,
but not be scared of, or confused about, that for which it’s
shorthand. Most of the materials I found for learning macros, including the
-Racket Guide, do a very good job explaining how patterns
-and templates work. I’m not going to regurgitate that here. Sometimes, we need to go a step beyond the pattern and template. Let’s
+Racket Guide, do a very good job explaining
+how
+patterns and templates work. So I won’t regurgitate that here. Sometimes, we need to go a step beyond the pattern and template. Let’s
look at some examples, how we can get confused, and how to get it
working. 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 struct
@@ -279,7 +280,7 @@ default. Only inside of our aif will it have a meani
value: 10 Inside the syntax-parameterize, it acts as an alias
for tmp. The alias behavior is created by
make-rename-transformer. If we try to use it outside of an aif form, and
-it isn’t otherwise defined, we get an error like we want: it: can only be used inside aif But we can still define it as a normal variable: 10 I stared at racket/splicing for the longest time. What does
+it isn’t otherwise defined, we get an error like we want: it: can only be used inside aif But we can still define it as a normal variable: 10 For a deeper look, see Keeping it Clean with Syntax Parameters. I stared at racket/splicing for the longest time. What does
it do? Why would I use it? Why is it in the Macros section of the
reference? Step one, cut a hole in the box
de-mythologize it. For example, using splicing-let like this: 0 x: undefined; cannot reference an identifier before its definition in module: 'program is equivalent to: 0 y: undefined; cannot reference an identifier before its definition in module: 'program This is the classic Lisp/Scheme/Racket idiom sometimes called "let
diff --git a/main.rkt b/main.rkt
index f940316..a9bf5c3 100644
--- a/main.rkt
+++ b/main.rkt
@@ -242,7 +242,7 @@ Let's start by looking closely at what the input actually @italic{is}:
(define-syntax (show-me stx)
(print stx)
#'(void))
-(show-me '(i am a list))
+(show-me '(+ 1 2))
]
The @racket[(print stx)] shows what our transformer is given: a syntax
@@ -674,8 +674,9 @@ but not be scared of, or confused about, that for which it's
shorthand.
Most of the materials I found for learning macros, including the
-Racket @italic{Guide}, do a very good job explaining how patterns
-and templates work. I'm not going to regurgitate that here.
+Racket @italic{Guide}, do a very good job explaining
+@hyperlink["http://docs.racket-lang.org/guide/pattern-macros.html" "how
+patterns and templates work"]. So I won't regurgitate that here.
Sometimes, we need to go a step beyond the pattern and template. Let's
look at some examples, how we can get confused, and how to get it
@@ -890,8 +891,10 @@ Using @racket[format-id] is convenient as it handles the tedium of
converting from syntax to symbol datum to string ... and all the way
back.
-Finally, here's a variation that accepts any number of name parts that
-are joined with hyphens:
+@subsubsection{Another example}
+
+Finally, here's a variation that accepts an arbitary number of name
+parts to be joined with hyphens:
@i[
(require (for-syntax racket/string racket/syntax))
@@ -909,6 +912,7 @@ are joined with hyphens:
(foo-bar-baz 50)
]
+
To review:
@itemize[
@@ -1301,6 +1305,8 @@ But we can still define @racket[it] as a normal variable:
it
]
+For a deeper look, see @hyperlink["http://www.schemeworkshop.org/2011/papers/Barzilay2011.pdf" "Keeping it Clean with Syntax Parameters"].
+
@; ----------------------------------------------------------------------------
@; ----------------------------------------------------------------------------
> (define-syntax (show-me stx) (print stx) #'(void)) > (show-me '(i am a list)) > (define-syntax (show-me stx) (print stx) #'(void)) > (show-me '(+ 1 2)) 4.1 Pattern variable vs. template—
> (require racket/stxparam) > (define-syntax-parameter it (lambda (stx) (raise-syntax-error (syntax-e stx) "can only be used inside aif"))) > (define-syntax-rule (aif condition true-expr false-expr) (let ([tmp condition]) (if tmp (syntax-parameterize ([it (make-rename-transformer #'tmp)]) true-expr) false-expr))) > (aif 10 (displayln it) (void)) > (aif #f (displayln it) (void)) > (displayln it) > (define it 10) > it 6 What’s the point of splicing-let?
> (displayln it) > (define it 10) > it 6 What’s the point of splicing-let?
> (require racket/splicing) > (splicing-let ([x 0]) (define (get-x) x)) ; get-x is visible out here: > (get-x) ; but x is not: > x > (define get-y (let ([y 0]) (lambda () y))) ; get-y is visible out here: > (get-y) ; but y is not: > y