fear-of-macros/Transform_.html
2016-06-05 12:45:37 -04:00

104 lines
89 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"/><title>3&nbsp;Transform!</title><link rel="stylesheet" type="text/css" href="scribble.css" title="default"/><link rel="stylesheet" type="text/css" href="racket.css" title="default"/><link rel="stylesheet" type="text/css" href="manual-style.css" title="default"/><link rel="stylesheet" type="text/css" href="manual-racket.css" title="default"/><link rel="stylesheet" type="text/css" href="gh.css" title="default"/><script type="text/javascript" src="scribble-common.js"></script><script type="text/javascript" src="manual-racket.js"></script><!--[if IE 6]><style type="text/css">.SIEHidden { overflow: hidden; }</style><![endif]--><meta name="keywords" content="Racket,macros,Scheme"><meta name="description" content="Practical Racket macros"><meta name="author" content="Greg Hendershott"><meta name="charset" content="utf-8"><link href='http://fonts.googleapis.com/css?family=Fenix' rel='stylesheet' type='text/css'><script type="text/javascript">var _gaq = _gaq || [];_gaq.push(['_setAccount', 'UA-29709446-1']);_gaq.push(['_setDomainName', 'greghendershott.com']);_gaq.push(['_trackPageview']);(function() {var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);})();</script></head><body id="scribble-racket-lang-org"><div class="tocset"><div class="tocview"><div class="tocviewlist tocviewlisttopspace"><div class="tocviewtitle"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,&quot;tocview_0&quot;);">&#9660;</a></td><td></td><td><a href="index.html" class="tocviewlink" data-pltdoc="x">Fear of Macros</a></td></tr></table></div><div class="tocviewsublisttop" style="display: block;" id="tocview_0"><table cellspacing="0" cellpadding="0"><tr><td align="right">1&nbsp;</td><td><a href="Preface.html" class="tocviewlink" data-pltdoc="x">Preface</a></td></tr><tr><td align="right">2&nbsp;</td><td><a href="Our_plan_of_attack.html" class="tocviewlink" data-pltdoc="x">Our plan of attack</a></td></tr><tr><td align="right">3&nbsp;</td><td><a href="" class="tocviewselflink" data-pltdoc="x">Transform!</a></td></tr><tr><td align="right">4&nbsp;</td><td><a href="pattern-matching.html" class="tocviewlink" data-pltdoc="x">Pattern matching:<span class="mywbr"> &nbsp;</span> syntax-<wbr></wbr>case and syntax-<wbr></wbr>rules</a></td></tr><tr><td align="right">5&nbsp;</td><td><a href="Syntax_parameters.html" class="tocviewlink" data-pltdoc="x">Syntax parameters</a></td></tr><tr><td align="right">6&nbsp;</td><td><a href="What_s_the_point_of_splicing-let_.html" class="tocviewlink" data-pltdoc="x">What&rsquo;s the point of <span class="RktSym"><span class="RktStxLink">splicing-<wbr></wbr>let</span></span>?</a></td></tr><tr><td align="right">7&nbsp;</td><td><a href="Robust_macros__syntax-parse.html" class="tocviewlink" data-pltdoc="x">Robust macros:<span class="mywbr"> &nbsp;</span> syntax-<wbr></wbr>parse</a></td></tr><tr><td align="right">8&nbsp;</td><td><a href="References_and_Acknowledgments.html" class="tocviewlink" data-pltdoc="x">References and Acknowledgments</a></td></tr><tr><td align="right">9&nbsp;</td><td><a href="Epilogue.html" class="tocviewlink" data-pltdoc="x">Epilogue</a></td></tr></table></div></div><div class="tocviewlist"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,&quot;tocview_1&quot;);">&#9658;</a></td><td>3&nbsp;</td><td><a href="" class="tocviewselflink" data-pltdoc="x">Transform!</a></td></tr></table><div class="tocviewsublistbottom" style="display: none;" id="tocview_1"><table cellspacing="0" cellpadding="0"><tr><td align="right">3.1&nbsp;</td><td><a href="#%28part._.What_is_a_syntax_transformer_%29" class="tocviewlink" data-pltdoc="x">What is a syntax transformer?</a></td></tr><tr><td align="right">3.2&nbsp;</td><td><a href="#%28part._.What_s_the_input_%29" class="tocviewlink" data-pltdoc="x">What&rsquo;s the input?</a></td></tr><tr><td align="right">3.3&nbsp;</td><td><a href="#%28part._.Actually_transforming_the_input%29" class="tocviewlink" data-pltdoc="x">Actually transforming the input</a></td></tr><tr><td align="right">3.4&nbsp;</td><td><a href="#%28part._.Compile_time_vs__run_time%29" class="tocviewlink" data-pltdoc="x">Compile time vs. run time</a></td></tr><tr><td align="right">3.5&nbsp;</td><td><a href="#%28part._begin-for-syntax%29" class="tocviewlink" data-pltdoc="x"><span class="RktSym"><span class="RktStxLink">begin-<wbr></wbr>for-<wbr></wbr>syntax</span></span></a></td></tr></table></div></div></div><div class="tocsub"><div class="tocsubtitle">On this page:</div><table class="tocsublist" cellspacing="0"><tr><td><span class="tocsublinknumber">3.1<tt>&nbsp;</tt></span><a href="#%28part._.What_is_a_syntax_transformer_%29" class="tocsubseclink" data-pltdoc="x">What is a syntax transformer?</a></td></tr><tr><td><span class="tocsublinknumber">3.2<tt>&nbsp;</tt></span><a href="#%28part._.What_s_the_input_%29" class="tocsubseclink" data-pltdoc="x">What&rsquo;s the input?</a></td></tr><tr><td><span class="tocsublinknumber">3.3<tt>&nbsp;</tt></span><a href="#%28part._.Actually_transforming_the_input%29" class="tocsubseclink" data-pltdoc="x">Actually transforming the input</a></td></tr><tr><td><span class="tocsublinknumber">3.4<tt>&nbsp;</tt></span><a href="#%28part._.Compile_time_vs__run_time%29" class="tocsubseclink" data-pltdoc="x">Compile time vs. run time</a></td></tr><tr><td><span class="tocsublinknumber">3.5<tt>&nbsp;</tt></span><a href="#%28part._begin-for-syntax%29" class="tocsubseclink" data-pltdoc="x"><span class="RktSym"><span class="RktStxLink">begin-<wbr></wbr>for-<wbr></wbr>syntax</span></span></a></td></tr></table></div></div><div class="maincolumn"><div class="main"><div class="navsettop"><span class="navleft"><div class="nosearchform"></div>&nbsp;&nbsp;</span><span class="navright">&nbsp;&nbsp;<a href="Our_plan_of_attack.html" title="backward to &quot;2 Our plan of attack&quot;" data-pltdoc="x">&larr; prev</a>&nbsp;&nbsp;<a href="index.html" title="up to &quot;Fear of Macros&quot;" data-pltdoc="x">up</a>&nbsp;&nbsp;<a href="pattern-matching.html" title="forward to &quot;4 Pattern matching: syntax-case and syntax-rules&quot;" data-pltdoc="x">next &rarr;</a></span>&nbsp;</div><h3>3<tt>&nbsp;</tt><a name="(part._.Transform_)"></a>Transform!</h3><p><table cellspacing="0" cellpadding="0"><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="stt">YOU ARE INSIDE A ROOM.</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="stt">THERE ARE KEYS ON THE GROUND.</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="stt">THERE IS A SHINY BRASS LAMP NEARBY.</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="stt"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="stt">IF YOU GO THE WRONG WAY, YOU WILL BECOME</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="stt">HOPELESSLY LOST AND CONFUSED.</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="stt"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="stt">&gt; pick up the keys</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="stt"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="stt">YOU HAVE A SYNTAX TRANSFORMER</span></p></td></tr></table></p><h4>3.1<tt>&nbsp;</tt><a name="(part._.What_is_a_syntax_transformer_)"></a>What is a syntax transformer?</h4><p>A syntax transformer is not one of the &#12488;&#12521;&#12531;&#12473;&#12501;&#12457;&#12540;&#12510;
<a href="http://en.wikipedia.org/wiki/Transformers">transformers</a>.</p><p>Instead, it is simply a function. The function takes syntax and
returns syntax. It transforms syntax.</p><p>Here&rsquo;s a transformer function that ignores its input syntax, and
always outputs syntax for a string literal:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktSym">foo</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/lambda.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#%28form._%28%28lib._racket%2Fprivate%2Fstxcase-scheme..rkt%29._syntax%29%29" class="RktStxLink" data-pltdoc="x">syntax</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"I am foo"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote><p>Using it:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">foo</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">"I am foo"</span></p></td></tr></table></blockquote><p>When we use <span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span>, we&rsquo;re making a transformer
<span style="font-style: italic">binding</span>. This tells the Racket compiler, "Whenever you
encounter a chunk of syntax starting with <span class="RktSym">foo</span>, please give it
to my transformer function, and replace it with the syntax I give back
to you." So Racket will give anything that looks like <span class="RktPn">(</span><span class="RktSym">foo</span><span class="stt"> </span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#%28form._%28%28lib._racket%2Fprivate%2Fstxcase-scheme..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span> to our function, and we can return new syntax to use
instead. Much like a search-and-replace.</p><p>Maybe you know that the usual way to define a function in Racket:</p><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#%28form._%28%28lib._racket%2Fprivate%2Fstxcase-scheme..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></p></blockquote><p>is shorthand for:</p><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">f</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/lambda.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#%28form._%28%28lib._racket%2Fprivate%2Fstxcase-scheme..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote><p>That shorthand lets you avoid typing <span class="RktSym"><a href="http://docs.racket-lang.org/reference/lambda.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span> and some parentheses.</p><p>Well there is a similar shorthand for <span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">also-foo</span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#%28form._%28%28lib._racket%2Fprivate%2Fstxcase-scheme..rkt%29._syntax%29%29" class="RktStxLink" data-pltdoc="x">syntax</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"I am also foo"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">also-foo</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">"I am also foo"</span></p></td></tr></table></blockquote><p>What we want to remember is that this is simply shorthand. We are
still defining a transformer function, which takes syntax and returns
syntax. Everything we do with macros, will be built on top of this
basic idea. It&rsquo;s not magic.</p><p>Speaking of shorthand, there is also a shorthand for <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#%28form._%28%28lib._racket%2Fprivate%2Fstxcase-scheme..rkt%29._syntax%29%29" class="RktStxLink" data-pltdoc="x">syntax</a></span>,
which is <span class="stt">#</span><span class="stt">&rsquo;</span><span class="stt"></span>:</p><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p><span class="stt">#</span><span class="stt">&rsquo;</span><span class="stt"></span> is short for <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#%28form._%28%28lib._racket%2Fprivate%2Fstxcase-scheme..rkt%29._syntax%29%29" class="RktStxLink" data-pltdoc="x">syntax</a></span> much like
<span class="stt"></span><span class="stt">&rsquo;</span><span class="stt"></span> is short for <span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">quote</a></span>.</p></blockquote></blockquote></blockquote><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">quoted-foo</span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktRdr">#'</span><span class="RktVal">"I am also foo, using #' instead of syntax"</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">quoted-foo</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">"I am also foo, using #' instead of syntax"</span></p></td></tr></table></blockquote><p>We&rsquo;ll use the <span class="stt">#</span><span class="stt">&rsquo;</span><span class="stt"></span> shorthand from now on.</p><p>Of course, we can emit syntax that is more interesting than a
string literal. How about returning <span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#%28def._%28%28lib._racket%2Fprivate%2Fmisc..rkt%29._displayln%29%29" class="RktValLink" data-pltdoc="x">displayln</a></span><span class="stt"> </span><span class="RktVal">"hi"</span><span class="RktPn">)</span>?</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">say-hi</span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#%28def._%28%28lib._racket%2Fprivate%2Fmisc..rkt%29._displayln%29%29" class="RktValLink" data-pltdoc="x">displayln</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"hi"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">say-hi</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktOut">hi</span></p></td></tr></table></blockquote><p>When Racket expands our program, it sees the occurrence of
<span class="RktPn">(</span><span class="RktSym">say-hi</span><span class="RktPn">)</span>, 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.</p><h4>3.2<tt>&nbsp;</tt><a name="(part._.What_s_the_input_)"></a>What&rsquo;s the input?</h4><p>Our examples so far have ignored the input syntax and output some
fixed syntax. But typically we will want to transform the input syntax
into something else.</p><p>Let&rsquo;s start by looking closely at what the input actually <span style="font-style: italic">is</span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">show-me</span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#%28def._%28%28quote._~23~25kernel%29._print%29%29" class="RktValLink" data-pltdoc="x">print</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/void.html#%28def._%28%28quote._~23~25kernel%29._void%29%29" class="RktValLink" data-pltdoc="x">void</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">show-me</span><span class="hspace">&nbsp;</span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">+</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="hspace">&nbsp;</span><span class="RktVal">2</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktOut">#&lt;syntax:10:0 (show-me (quote (+ 1 2)))&gt;</span></p></td></tr></table></blockquote><p>The <span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#%28def._%28%28quote._~23~25kernel%29._print%29%29" class="RktValLink" data-pltdoc="x">print</a></span><span class="stt"> </span><span class="RktSym">stx</span><span class="RktPn">)</span> shows what our transformer is given: a syntax
object.</p><p>A syntax object consists of several things. The first part is the
S-expression representing the code, such as <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">+</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktVal">)</span>.</p><p>Racket syntax is also decorated with some interesting information such
as the source file, line number, and column. Finally, it has
information about lexical scoping (which you don&rsquo;t need to worry about
now, but will turn out to be important later.)</p><p>There are a variety of functions available to access a syntax object.
Let&rsquo;s define a piece of syntax:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="hspace">&nbsp;</span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#%28form._%28%28quote._~23~25kernel%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"true"</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktVal">#f</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="stt">&gt; </span><span class="RktSym">stx</span></td></tr><tr><td><p><span class="RktRes">#&lt;syntax:11:0 (if x (list "true") #f)&gt;</span></p></td></tr></table></blockquote><p>Now let&rsquo;s use functions that access the syntax object. The source
information functions are:</p><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-source%29%29" class="RktValLink" data-pltdoc="x">syntax-source</a></span><span class="stt"> </span><span class="RktSym">stx</span><span class="RktPn">)</span> is returning <span class="RktVal">'</span><span class="RktVal">eval</span>,
only because of how I&rsquo;m generating this documentation, using an
evaluator to run code snippets in Scribble. Normally this would be
something like "my-file.rkt".</p></blockquote></blockquote></blockquote><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-source%29%29" class="RktValLink" data-pltdoc="x">syntax-source</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">'eval</span></p></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-line%29%29" class="RktValLink" data-pltdoc="x">syntax-line</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">11</span></p></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-column%29%29" class="RktValLink" data-pltdoc="x">syntax-column</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">0</span></p></td></tr></table></blockquote><p>More interesting is the syntax "stuff" itself. <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3edatum%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;datum</a></span>
converts it completely into an S-expression:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3edatum%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;datum</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">'(if<span class="stt"> </span>x<span class="stt"> </span>(list<span class="stt"> </span>"true")<span class="stt"> </span>#f)</span></p></td></tr></table></blockquote><p>Whereas <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-e%29%29" class="RktValLink" data-pltdoc="x">syntax-e</a></span> only goes "one level down". It may return a
list that has syntax objects:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-e%29%29" class="RktValLink" data-pltdoc="x">syntax-e</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">'(#&lt;syntax:11:0 if&gt;<span class="stt"> </span>#&lt;syntax:11:0 x&gt;<span class="stt"> </span>#&lt;syntax:11:0 (list "true")&gt;<span class="stt"> </span>#&lt;syntax:11:0 #f&gt;)</span></p></td></tr></table></blockquote><p>Each of those syntax objects could be converted by <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-e%29%29" class="RktValLink" data-pltdoc="x">syntax-e</a></span>,
and so on recursively&#8212;<wbr></wbr>which is what <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3edatum%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;datum</a></span> does.</p><p>In most cases, <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3elist%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;list</a></span> gives the same result as
<span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-e%29%29" class="RktValLink" data-pltdoc="x">syntax-e</a></span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3elist%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;list</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">'(#&lt;syntax:11:0 if&gt;<span class="stt"> </span>#&lt;syntax:11:0 x&gt;<span class="stt"> </span>#&lt;syntax:11:0 (list "true")&gt;<span class="stt"> </span>#&lt;syntax:11:0 #f&gt;)</span></p></td></tr></table></blockquote><p>(When would <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-e%29%29" class="RktValLink" data-pltdoc="x">syntax-e</a></span> and <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3elist%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;list</a></span> differ? Let&rsquo;s
not get side-tracked now.)</p><p>When we want to transform syntax, we&rsquo;ll generally take the pieces we
were given, maybe rearrange their order, perhaps change some of the
pieces, and often introduce brand-new pieces.</p><h4>3.3<tt>&nbsp;</tt><a name="(part._.Actually_transforming_the_input)"></a>Actually transforming the input</h4><p>Let&rsquo;s write a transformer function that reverses the syntax it was
given:</p><p><div class="SIntrapara"><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>The <span class="RktSym"><a href="http://docs.racket-lang.org/reference/values.html#%28def._%28%28quote._~23~25kernel%29._values%29%29" class="RktValLink" data-pltdoc="x">values</a></span> at the end of the example allows the
result to evaluate nicely. Try
<span class="RktPn">(</span><span class="RktSym">reverse-me</span><span class="stt"> </span><span class="RktVal">"backwards"</span><span class="stt"> </span><span class="RktVal">"am"</span><span class="stt"> </span><span class="RktVal">"i"</span><span class="RktPn">)</span> to see why it&rsquo;s handy.</p></blockquote></blockquote></blockquote></div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">reverse-me</span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._datum-~3esyntax%29%29" class="RktValLink" data-pltdoc="x">datum-&gt;syntax</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Fprivate%2Flist..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cdr%29%29" class="RktValLink" data-pltdoc="x">cdr</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3edatum%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;datum</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">reverse-me</span><span class="hspace">&nbsp;</span><span class="RktVal">"backwards"</span><span class="hspace">&nbsp;</span><span class="RktVal">"am"</span><span class="hspace">&nbsp;</span><span class="RktVal">"i"</span><span class="hspace">&nbsp;</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/values.html#%28def._%28%28quote._~23~25kernel%29._values%29%29" class="RktValLink" data-pltdoc="x">values</a></span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">"i"</span></p></td></tr><tr><td><p><span class="RktRes">"am"</span></p></td></tr><tr><td><p><span class="RktRes">"backwards"</span></p></td></tr></table></blockquote></div></p><p>Understand Yoda, can we. Great, but how does this work?</p><p>First we take the input syntax, and give it to
<span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3edatum%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;datum</a></span>. This converts the syntax into a plain old
list:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3edatum%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;datum</a></span><span class="hspace">&nbsp;</span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktSym">reverse-me</span><span class="hspace">&nbsp;</span><span class="RktVal">"backwards"</span><span class="hspace">&nbsp;</span><span class="RktVal">"am"</span><span class="hspace">&nbsp;</span><span class="RktVal">"i"</span><span class="hspace">&nbsp;</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/values.html#%28def._%28%28quote._~23~25kernel%29._values%29%29" class="RktValLink" data-pltdoc="x">values</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">'(reverse-me<span class="stt"> </span>"backwards"<span class="stt"> </span>"am"<span class="stt"> </span>"i"<span class="stt"> </span>values)</span></p></td></tr></table></blockquote><p>Using <span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cdr%29%29" class="RktValLink" data-pltdoc="x">cdr</a></span> slices off the first item of the list,
<span class="RktSym">reverse-me</span>, leaving the remainder:
<span class="RktPn">(</span><span class="RktVal">"backwards"</span><span class="stt"> </span><span class="RktVal">"am"</span><span class="stt"> </span><span class="RktVal">"i"</span><span class="stt"> </span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/values.html#%28def._%28%28quote._~23~25kernel%29._values%29%29" class="RktValLink" data-pltdoc="x">values</a></span><span class="RktPn">)</span>. Passing that to
<span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Fprivate%2Flist..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span> changes it to <span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/values.html#%28def._%28%28quote._~23~25kernel%29._values%29%29" class="RktValLink" data-pltdoc="x">values</a></span><span class="stt"> </span><span class="RktVal">"i"</span><span class="stt"> </span><span class="RktVal">"am"</span><span class="stt"> </span><span class="RktVal">"backwards"</span><span class="RktPn">)</span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Fprivate%2Flist..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cdr%29%29" class="RktValLink" data-pltdoc="x">cdr</a></span><span class="hspace">&nbsp;</span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">reverse-me</span><span class="hspace">&nbsp;</span><span class="RktVal">"backwards"</span><span class="hspace">&nbsp;</span><span class="RktVal">"am"</span><span class="hspace">&nbsp;</span><span class="RktVal">"i"</span><span class="hspace">&nbsp;</span><span class="RktVal">values</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">'(values<span class="stt"> </span>"i"<span class="stt"> </span>"am"<span class="stt"> </span>"backwards")</span></p></td></tr></table></blockquote><p>Finally we use <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._datum-~3esyntax%29%29" class="RktValLink" data-pltdoc="x">datum-&gt;syntax</a></span> to convert this back to
<span class="RktSym"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#%28form._%28%28lib._racket%2Fprivate%2Fstxcase-scheme..rkt%29._syntax%29%29" class="RktStxLink" data-pltdoc="x">syntax</a></span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._datum-~3esyntax%29%29" class="RktValLink" data-pltdoc="x">datum-&gt;syntax</a></span><span class="hspace">&nbsp;</span><span class="RktVal">#f</span><span class="hspace">&nbsp;</span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">values</span><span class="hspace">&nbsp;</span><span class="RktVal">"i"</span><span class="hspace">&nbsp;</span><span class="RktVal">"am"</span><span class="hspace">&nbsp;</span><span class="RktVal">"backwards"</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#&lt;syntax (values "i" "am" "backwards")&gt;</span></p></td></tr></table></blockquote><p>That&rsquo;s what our transformer function gives back to the Racket
compiler, and <span style="font-style: italic">that</span> syntax is evaluated:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/values.html#%28def._%28%28quote._~23~25kernel%29._values%29%29" class="RktValLink" data-pltdoc="x">values</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"i"</span><span class="hspace">&nbsp;</span><span class="RktVal">"am"</span><span class="hspace">&nbsp;</span><span class="RktVal">"backwards"</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">"i"</span></p></td></tr><tr><td><p><span class="RktRes">"am"</span></p></td></tr><tr><td><p><span class="RktRes">"backwards"</span></p></td></tr></table></blockquote><h4>3.4<tt>&nbsp;</tt><a name="(part._.Compile_time_vs__run_time)"></a>Compile time vs. run time</h4><p><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">foo</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktSym">stx</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pipeports.html#%28def._%28%28quote._~23~25kernel%29._make-pipe%29%29" class="RktValLink" data-pltdoc="x">make-pipe</a></span><span class="RktPn">)</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktCmt">;Ce</span><span class="hspace">&nbsp;</span><span class="RktCmt">n'est</span><span class="hspace">&nbsp;</span><span class="RktCmt">pas</span><span class="hspace">&nbsp;</span><span class="RktCmt">le</span><span class="hspace">&nbsp;</span><span class="RktCmt">temps</span><span class="hspace">&nbsp;</span><span class="RktCmt">d'ex&#233;cution</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktMeta"></span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#%28form._%28%28lib._racket%2Fprivate%2Fstxcase-scheme..rkt%29._syntax%29%29" class="RktStxLink" data-pltdoc="x">#'</a></span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/void.html#%28def._%28%28quote._~23~25kernel%29._void%29%29" class="RktValLink" data-pltdoc="x">void</a></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr></table></p><p>Normal Racket code runs at ... run time. Duh.</p><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>Instead of "compile time vs. run time", you may hear it
described as "syntax phase vs. runtime phase". Same difference.</p></blockquote></blockquote></blockquote><p>But a syntax transformer is called by Racket as part of the process of
parsing, expanding, and compiling our program. In other words, our
syntax transformer function is evaluated at compile time.</p><p>This aspect of macros lets you do things that simply aren&rsquo;t possible
in normal code. One of the classic examples is something like the
Racket form, <span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#%28form._%28%28quote._~23~25kernel%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span>:</p><p><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#%28form._%28%28quote._~23~25kernel%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span><span class="stt"> </span><span class="RktSym">&lt;condition&gt;</span><span class="stt"> </span><span class="RktSym">&lt;true-expression&gt;</span><span class="stt"> </span><span class="RktSym">&lt;false-expression&gt;</span><span class="RktPn">)</span></p><p>If we implemented <span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#%28form._%28%28quote._~23~25kernel%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span> as a function, all of the arguments
would be evaluated before being provided to the function.</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">our-if</span><span class="hspace">&nbsp;</span><span class="RktSym">condition</span><span class="hspace">&nbsp;</span><span class="RktSym">true-expr</span><span class="hspace">&nbsp;</span><span class="RktSym">false-expr</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#%28form._%28%28lib._racket%2Fprivate%2Fletstx-scheme..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span><span class="hspace">&nbsp;</span><span class="RktPn">[</span><span class="RktSym">condition</span><span class="hspace">&nbsp;</span><span class="RktSym">true-expr</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">[</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#%28form._%28%28lib._racket%2Fprivate%2Fletstx-scheme..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace">&nbsp;</span><span class="RktSym">false-expr</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">our-if</span><span class="hspace">&nbsp;</span><span class="RktVal">#t</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">"true"</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">"false"</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><p><span class="RktRes">"true"</span></p></td></tr></table></blockquote><p>That seems to work. However, how about this:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">display-and-return</span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#%28def._%28%28lib._racket%2Fprivate%2Fmisc..rkt%29._displayln%29%29" class="RktValLink" data-pltdoc="x">displayln</a></span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">our-if</span><span class="hspace">&nbsp;</span><span class="RktVal">#t</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">display-and-return</span><span class="hspace">&nbsp;</span><span class="RktVal">"true"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">display-and-return</span><span class="hspace">&nbsp;</span><span class="RktVal">"false"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><table cellspacing="0" cellpadding="0"><tr><td><p><span class="RktOut">true</span></p></td></tr><tr><td><p><span class="RktOut">false</span></p></td></tr></table></td></tr><tr><td><p><span class="RktRes">"true"</span></p></td></tr></table></blockquote><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>One answer is that functional programming is good, and
side-effects are bad. But avoiding side-effects isn&rsquo;t always
practical.</p></blockquote></blockquote></blockquote><p>Oops. Because the expressions have a side-effect, it&rsquo;s obvious that
they are both evaluated. And that could be a problem&#8212;<wbr></wbr>what if the
side-effect includes deleting a file on disk? You wouldn&rsquo;t want
<span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#%28form._%28%28quote._~23~25kernel%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span><span class="stt"> </span><span class="RktSym">user-wants-file-deleted?</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Filesystem.html#%28def._%28%28quote._~23~25kernel%29._delete-file%29%29" class="RktValLink" data-pltdoc="x">delete-file</a></span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/void.html#%28def._%28%28quote._~23~25kernel%29._void%29%29" class="RktValLink" data-pltdoc="x">void</a></span><span class="RktPn">)</span><span class="RktPn">)</span> to delete
a file even when <span class="RktSym">user-wants-file-deleted?</span> is <span class="RktVal">#f</span>.</p><p>So this simply can&rsquo;t work as a plain function. However a syntax
transformer can rearrange the syntax &ndash; rewrite the code &ndash; at compile
time. The pieces of syntax are moved around, but they aren&rsquo;t actually
evaluated until run time.</p><p>Here is one way to do this:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">our-if-v2</span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3elist%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;list</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._datum-~3esyntax%29%29" class="RktValLink" data-pltdoc="x">datum-&gt;syntax</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="hspace">&nbsp;</span><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">cond</span><span class="hspace">&nbsp;</span><span class="RktVal">[</span><span class="RktRdr">,</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cadr%29%29" class="RktValLink" data-pltdoc="x">cadr</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktRdr">,</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._caddr%29%29" class="RktValLink" data-pltdoc="x">caddr</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="RktPn">)</span><span class="RktVal">]</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">[</span><span class="RktVal">else</span><span class="hspace">&nbsp;</span><span class="RktRdr">,</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cadddr%29%29" class="RktValLink" data-pltdoc="x">cadddr</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="RktPn">)</span><span class="RktVal">]</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">our-if-v2</span><span class="hspace">&nbsp;</span><span class="RktVal">#t</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">display-and-return</span><span class="hspace">&nbsp;</span><span class="RktVal">"true"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">display-and-return</span><span class="hspace">&nbsp;</span><span class="RktVal">"false"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><p><span class="RktOut">true</span></p></td></tr><tr><td><p><span class="RktRes">"true"</span></p></td></tr><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">our-if-v2</span><span class="hspace">&nbsp;</span><span class="RktVal">#f</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">display-and-return</span><span class="hspace">&nbsp;</span><span class="RktVal">"true"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">display-and-return</span><span class="hspace">&nbsp;</span><span class="RktVal">"false"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><p><span class="RktOut">false</span></p></td></tr><tr><td><p><span class="RktRes">"false"</span></p></td></tr></table></blockquote><p>That gave the right answer. But how? Let&rsquo;s pull out the transformer
function itself, and see what it did. We start with an example of some
input syntax:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="hspace">&nbsp;</span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktSym">our-if-v2</span><span class="hspace">&nbsp;</span><span class="RktVal">#t</span><span class="hspace">&nbsp;</span><span class="RktVal">"true"</span><span class="hspace">&nbsp;</span><span class="RktVal">"false"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#%28def._%28%28lib._racket%2Fprivate%2Fmisc..rkt%29._displayln%29%29" class="RktValLink" data-pltdoc="x">displayln</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktOut">#&lt;syntax:32:0 (our-if-v2 #t "true" "false")&gt;</span></p></td></tr></table></blockquote><p>1. We take the original syntax, and use <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3elist%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;list</a></span> to
change it into a <span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span> of syntax objects:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3elist%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;list</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#%28def._%28%28lib._racket%2Fprivate%2Fmisc..rkt%29._displayln%29%29" class="RktValLink" data-pltdoc="x">displayln</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktOut">(#&lt;syntax:32:0 our-if-v2&gt; #&lt;syntax:32:0 #t&gt; #&lt;syntax:32:0 "true"&gt; #&lt;syntax:32:0 "false"&gt;)</span></p></td></tr></table></blockquote><p>2. To change this into a Racket <span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#%28form._%28%28lib._racket%2Fprivate%2Fletstx-scheme..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> form, we need to take
the three interesting pieces&#8212;<wbr></wbr>the condition, true-expression, and
false-expression&#8212;<wbr></wbr>from the list using <span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cadr%29%29" class="RktValLink" data-pltdoc="x">cadr</a></span>, <span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._caddr%29%29" class="RktValLink" data-pltdoc="x">caddr</a></span>,
and <span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cadddr%29%29" class="RktValLink" data-pltdoc="x">cadddr</a></span> and arrange them into a <span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#%28form._%28%28lib._racket%2Fprivate%2Fletstx-scheme..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> form:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">cond</span><span class="hspace">&nbsp;</span><span class="RktVal">[</span><span class="RktRdr">,</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cadr%29%29" class="RktValLink" data-pltdoc="x">cadr</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktRdr">,</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._caddr%29%29" class="RktValLink" data-pltdoc="x">caddr</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="RktPn">)</span><span class="RktVal">]</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">[</span><span class="RktVal">else</span><span class="hspace">&nbsp;</span><span class="RktRdr">,</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cadddr%29%29" class="RktValLink" data-pltdoc="x">cadddr</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="RktPn">)</span><span class="RktVal">]</span><span class="RktVal">)</span></td></tr></table></blockquote><p>3. Finally, we change that into <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#%28form._%28%28lib._racket%2Fprivate%2Fstxcase-scheme..rkt%29._syntax%29%29" class="RktStxLink" data-pltdoc="x">syntax</a></span> using
<span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._datum-~3esyntax%29%29" class="RktValLink" data-pltdoc="x">datum-&gt;syntax</a></span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._datum-~3esyntax%29%29" class="RktValLink" data-pltdoc="x">datum-&gt;syntax</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="hspace">&nbsp;</span><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">cond</span><span class="hspace">&nbsp;</span><span class="RktVal">[</span><span class="RktRdr">,</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cadr%29%29" class="RktValLink" data-pltdoc="x">cadr</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktRdr">,</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._caddr%29%29" class="RktValLink" data-pltdoc="x">caddr</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="RktPn">)</span><span class="RktVal">]</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">[</span><span class="RktVal">else</span><span class="hspace">&nbsp;</span><span class="RktRdr">,</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cadddr%29%29" class="RktValLink" data-pltdoc="x">cadddr</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="RktPn">)</span><span class="RktVal">]</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><p><span class="RktRes">#&lt;syntax (cond (#t "true") (else "fals...&gt;</span></p></td></tr></table></blockquote><p>So that works, but using <span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cadddr%29%29" class="RktValLink" data-pltdoc="x">cadddr</a></span> etc. to destructure a list is
painful and error-prone. Maybe you know Racket&rsquo;s <span class="RktSym"><a href="http://docs.racket-lang.org/reference/match.html#%28form._%28%28lib._racket%2Fmatch..rkt%29._match%29%29" class="RktStxLink" data-pltdoc="x">match</a></span>?
Using that would let us do pattern-matching.</p><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>Notice that we don&rsquo;t care about the first item in the
syntax list. We didn&rsquo;t take <span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._car%29%29" class="RktValLink" data-pltdoc="x">car</a></span><span class="stt"> </span><span class="RktSym">xs</span><span class="RktPn">)</span> in our-if-v2, and we
didn&rsquo;t use <span class="RktSym">name</span> when we used pattern-matching. In general, a
syntax transformer won&rsquo;t care about that, because it is the name of
the transformer binding. In other words, a macro usually doesn&rsquo;t care
about its own name.</p></blockquote></blockquote></blockquote><p>Instead of:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">our-if-v2</span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3elist%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;list</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._datum-~3esyntax%29%29" class="RktValLink" data-pltdoc="x">datum-&gt;syntax</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="hspace">&nbsp;</span><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">cond</span><span class="hspace">&nbsp;</span><span class="RktVal">[</span><span class="RktRdr">,</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cadr%29%29" class="RktValLink" data-pltdoc="x">cadr</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktRdr">,</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._caddr%29%29" class="RktValLink" data-pltdoc="x">caddr</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="RktPn">)</span><span class="RktVal">]</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">[</span><span class="RktVal">else</span><span class="hspace">&nbsp;</span><span class="RktRdr">,</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._cadddr%29%29" class="RktValLink" data-pltdoc="x">cadddr</a></span><span class="hspace">&nbsp;</span><span class="RktSym">xs</span><span class="RktPn">)</span><span class="RktVal">]</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote><p>We can write:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">our-if-using-match</span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/match.html#%28form._%28%28lib._racket%2Fmatch..rkt%29._match%29%29" class="RktStxLink" data-pltdoc="x">match</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3elist%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;list</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace">&nbsp;</span><span class="RktSym">name</span><span class="hspace">&nbsp;</span><span class="RktSym">condition</span><span class="hspace">&nbsp;</span><span class="RktSym">true-expr</span><span class="hspace">&nbsp;</span><span class="RktSym">false-expr</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._datum-~3esyntax%29%29" class="RktValLink" data-pltdoc="x">datum-&gt;syntax</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="hspace">&nbsp;</span><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">cond</span><span class="hspace">&nbsp;</span><span class="RktVal">[</span><span class="RktRdr">,</span><span class="RktSym">condition</span><span class="hspace">&nbsp;</span><span class="RktRdr">,</span><span class="RktSym">true-expr</span><span class="RktVal">]</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">[</span><span class="RktVal">else</span><span class="hspace">&nbsp;</span><span class="RktRdr">,</span><span class="RktSym">false-expr</span><span class="RktVal">]</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote><p>Great. Now let&rsquo;s try using it:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">our-if-using-match</span><span class="hspace">&nbsp;</span><span class="RktVal">#t</span><span class="hspace">&nbsp;</span><span class="RktVal">"true"</span><span class="hspace">&nbsp;</span><span class="RktVal">"false"</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">match: undefined;</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;</span><span class="RktErr">cannot reference an identifier before its definition</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">in module: 'program</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">phase: 1</span></p></td></tr></table></blockquote><p>Oops. It&rsquo;s complaining that <span class="RktSym"><a href="http://docs.racket-lang.org/reference/match.html#%28form._%28%28lib._racket%2Fmatch..rkt%29._match%29%29" class="RktStxLink" data-pltdoc="x">match</a></span> isn&rsquo;t defined.</p><p>Our transformer function is working at compile time, not run time. And
at compile time, only <span class="RktSym">racket/base</span> is required for you
automatically&#8212;<wbr></wbr>not the full <span class="RktSym">racket</span>.</p><p>Anything beyond <span class="RktSym">racket/base</span>, we have to require
ourselves&#8212;<wbr></wbr>and require it for compile time using the
<span class="RktSym"><a href="http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for-syntax%29%29" class="RktStxLink" data-pltdoc="x">for-syntax</a></span> form of <span class="RktSym"><a href="http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._require%29%29" class="RktStxLink" data-pltdoc="x">require</a></span>.</p><p>In this case, instead of using plain <span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._require%29%29" class="RktStxLink" data-pltdoc="x">require</a></span><span class="stt"> </span><span class="RktSym">racket/match</span><span class="RktPn">)</span>,
we want <span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._require%29%29" class="RktStxLink" data-pltdoc="x">require</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for-syntax%29%29" class="RktStxLink" data-pltdoc="x">for-syntax</a></span><span class="stt"> </span><span class="RktSym">racket/match</span><span class="RktPn">)</span><span class="RktPn">)</span>&#8212;<wbr></wbr>the
<span class="RktSym"><a href="http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for-syntax%29%29" class="RktStxLink" data-pltdoc="x">for-syntax</a></span> part meaning, "for compile time".</p><p>So let&rsquo;s try that:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._require%29%29" class="RktStxLink" data-pltdoc="x">require</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for-syntax%29%29" class="RktStxLink" data-pltdoc="x">for-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktSym">racket/match</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">our-if-using-match-v2</span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/match.html#%28form._%28%28lib._racket%2Fmatch..rkt%29._match%29%29" class="RktStxLink" data-pltdoc="x">match</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._syntax-~3elist%29%29" class="RktValLink" data-pltdoc="x">syntax-&gt;list</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28quote._~23~25kernel%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace">&nbsp;</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#%28form._%28%28lib._racket%2Fprivate%2Fstxcase-scheme..rkt%29.__%29%29" class="RktStxLink" data-pltdoc="x">_</a></span><span class="hspace">&nbsp;</span><span class="RktSym">condition</span><span class="hspace">&nbsp;</span><span class="RktSym">true-expr</span><span class="hspace">&nbsp;</span><span class="RktSym">false-expr</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#%28def._%28%28quote._~23~25kernel%29._datum-~3esyntax%29%29" class="RktValLink" data-pltdoc="x">datum-&gt;syntax</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="hspace">&nbsp;</span><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">cond</span><span class="hspace">&nbsp;</span><span class="RktVal">[</span><span class="RktRdr">,</span><span class="RktSym">condition</span><span class="hspace">&nbsp;</span><span class="RktRdr">,</span><span class="RktSym">true-expr</span><span class="RktVal">]</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">[</span><span class="RktVal">else</span><span class="hspace">&nbsp;</span><span class="RktRdr">,</span><span class="RktSym">false-expr</span><span class="RktVal">]</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">our-if-using-match-v2</span><span class="hspace">&nbsp;</span><span class="RktVal">#t</span><span class="hspace">&nbsp;</span><span class="RktVal">"true"</span><span class="hspace">&nbsp;</span><span class="RktVal">"false"</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">"true"</span></p></td></tr></table></blockquote><p>Joy.</p><h4>3.5<tt>&nbsp;</tt><a name="(part._begin-for-syntax)"></a><span class="RktSym"><a href="http://docs.racket-lang.org/reference/begin.html#%28form._%28%28quote._~23~25kernel%29._begin-for-syntax%29%29" class="RktStxLink" data-pltdoc="x">begin-for-syntax</a></span></h4><p>We used <span class="RktSym"><a href="http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for-syntax%29%29" class="RktStxLink" data-pltdoc="x">for-syntax</a></span> to <span class="RktSym"><a href="http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._require%29%29" class="RktStxLink" data-pltdoc="x">require</a></span> the
<span class="RktSym">racket/match</span> module because we needed to use <span class="RktSym"><a href="http://docs.racket-lang.org/reference/match.html#%28form._%28%28lib._racket%2Fmatch..rkt%29._match%29%29" class="RktStxLink" data-pltdoc="x">match</a></span>
at compile time.</p><p>What if we wanted to define our own helper function to be used by a
macro? One way to do that is put it in another module, and
<span class="RktSym"><a href="http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._require%29%29" class="RktStxLink" data-pltdoc="x">require</a></span> it using <span class="RktSym"><a href="http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for-syntax%29%29" class="RktStxLink" data-pltdoc="x">for-syntax</a></span>, just like we did with
the <span class="RktSym">racket/match</span> module.</p><p>If instead we want to put the helper in the same module, we can&rsquo;t
simply <span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span> it and use it&#8212;<wbr></wbr>the definition would exist at
run time, but we need it at compile time. The answer is to put the
definition of the helper function(s) inside <span class="RktSym"><a href="http://docs.racket-lang.org/reference/begin.html#%28form._%28%28quote._~23~25kernel%29._begin-for-syntax%29%29" class="RktStxLink" data-pltdoc="x">begin-for-syntax</a></span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/begin.html#%28form._%28%28quote._~23~25kernel%29._begin-for-syntax%29%29" class="RktStxLink" data-pltdoc="x">begin-for-syntax</a></span></td></tr><tr><td><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">my-helper-function</span><span class="hspace">&nbsp;</span><span class="RktSym">....</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;</span><span class="RktSym">....</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">macro-using-my-helper-function</span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">my-helper-function</span><span class="hspace">&nbsp;</span><span class="RktSym">....</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktSym">....</span><span class="RktPn">)</span></td></tr></table></blockquote><p>In the simple case, we can also use <span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-for-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-for-syntax</a></span>, which
composes <span class="RktSym"><a href="http://docs.racket-lang.org/reference/begin.html#%28form._%28%28quote._~23~25kernel%29._begin-for-syntax%29%29" class="RktStxLink" data-pltdoc="x">begin-for-syntax</a></span> and <span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-for-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-for-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">my-helper-function</span><span class="hspace">&nbsp;</span><span class="RktSym">....</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktSym">....</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-syntax%29%29" class="RktStxLink" data-pltdoc="x">define-syntax</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">macro-using-my-helper-function</span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">my-helper-function</span><span class="hspace">&nbsp;</span><span class="RktSym">....</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktSym">....</span><span class="RktPn">)</span></td></tr></table></blockquote><p>To review:</p><ul><li><p>Syntax transformers work at compile time, not run time. The good
news is this means we can do things like rearrange the pieces of
syntax without evaluating them. We can implement forms like
<span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#%28form._%28%28quote._~23~25kernel%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span> that simply couldn&rsquo;t work properly as run time functions.</p></li><li><p>More good news is that there isn&rsquo;t some special, weird language
for writing syntax transformers. We can write these transformer
functions using the Racket language we already know and love.</p></li><li><p>The semi-bad news is that the familiarity can make it easy to forget
that we&rsquo;re not working at run time. Sometimes that&rsquo;s important to
remember.</p><ul><li><p>For example only <span class="RktSym">racket/base</span> is required for us
automatically. If we need other modules, we have to require them, and
do so <span style="font-style: italic">for compile time</span> using <span class="RktSym"><a href="http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for-syntax%29%29" class="RktStxLink" data-pltdoc="x">for-syntax</a></span>.</p></li><li><p>Similarly, if we want to define helper functions in the same
file/module as the macros that use them, we need to wrap the
definitions inside a <span class="RktSym"><a href="http://docs.racket-lang.org/reference/begin.html#%28form._%28%28quote._~23~25kernel%29._begin-for-syntax%29%29" class="RktStxLink" data-pltdoc="x">begin-for-syntax</a></span> form. Doing so makes
them available at compile time.</p></li></ul></li></ul><div class="navsetbottom"><span class="navleft"><div class="nosearchform"></div>&nbsp;&nbsp;</span><span class="navright">&nbsp;&nbsp;<a href="Our_plan_of_attack.html" title="backward to &quot;2 Our plan of attack&quot;" data-pltdoc="x">&larr; prev</a>&nbsp;&nbsp;<a href="index.html" title="up to &quot;Fear of Macros&quot;" data-pltdoc="x">up</a>&nbsp;&nbsp;<a href="pattern-matching.html" title="forward to &quot;4 Pattern matching: syntax-case and syntax-rules&quot;" data-pltdoc="x">next &rarr;</a></span>&nbsp;</div></div></div><div id="contextindicator">&nbsp;</div></body></html>