www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 73fa26c5088ee1679fdb5e847ab493729f5d54d3
parent 6e0c918e4de43eb31fd5190240a4360ea03947ad
Author: Greg Hendershott <greghendershott@gmail.com>
Date:   Thu, 25 Oct 2012 18:16:17 -0400

Prose edits for syntax parameter section.

Diffstat:
Mindex.html | 45+++++++++++++++++++++++----------------------
Mmain.rkt | 70+++++++++++++++++++++++++++++++++++++++++-----------------------------
2 files changed, 64 insertions(+), 51 deletions(-)

diff --git a/index.html b/index.html @@ -2,7 +2,7 @@ <html><head><meta http-equiv="content-type" content="text-html; charset=utf-8" /><title>Fear of Macros</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="scribble-style.css" title="default" /><link rel="stylesheet" type="text/css" href="gh.css" title="default" /><script type="text/javascript" src="scribble-common.js"></script><!--[if IE 6]><style type="text/css">.SIEHidden { overflow: hidden; }</style><![endif]--></head><body id="scribble-racket-lang-org"><div class="tocset"><div class="tocview"><div class="tocviewlist" style="margin-bottom: 1em;"><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;);">&#9658;</a></td><td></td><td><a href="" class="tocviewselflink" pltdoc="x">Fear of Macros</a></td></tr></table></div><div class="tocviewsublistonly" style="display: none;" id="tocview_0"><table cellspacing="0" cellpadding="0"><tr><td align="right">1&nbsp;</td><td><a href="#(part._.Introduction)" class="tocviewlink" pltdoc="x">Introduction</a></td></tr><tr><td align="right">2&nbsp;</td><td><a href="#(part._.The_plan_of_attack)" class="tocviewlink" pltdoc="x">The plan of attack</a></td></tr><tr><td align="right">3&nbsp;</td><td><a href="#(part._.Transformers)" class="tocviewlink" pltdoc="x">Transformers</a></td></tr><tr><td align="right">4&nbsp;</td><td><a href="#(part._.Pattern_matching__syntax-case_and_syntax-rules)" class="tocviewlink" pltdoc="x">Pattern matching:<span class="mywbr"> </span> syntax-<wbr></wbr>case and syntax-<wbr></wbr>rules</a></td></tr><tr><td align="right">5&nbsp;</td><td><a href="#(part._.Syntax_parameters)" class="tocviewlink" pltdoc="x">Syntax parameters</a></td></tr><tr><td align="right">6&nbsp;</td><td><a href="#(part._.Robust_macros__syntax-parse)" class="tocviewlink" pltdoc="x">Robust macros:<span class="mywbr"> </span> syntax-<wbr></wbr>parse</a></td></tr><tr><td align="right">7&nbsp;</td><td><a href="#(part._.Other_questions)" class="tocviewlink" pltdoc="x">Other questions</a></td></tr><tr><td align="right">8&nbsp;</td><td><a href="#(part._.References_.Acknowledgments)" class="tocviewlink" pltdoc="x">References/<span class="mywbr"> </span>Acknowledgments</a></td></tr><tr><td align="right">9&nbsp;</td><td><a href="#(part._.Epilogue)" class="tocviewlink" pltdoc="x">Epilogue</a></td></tr></table></div></div></div><div class="tocsub"><table class="tocsublist" cellspacing="0"><tr><td><span class="tocsublinknumber">1<tt>&nbsp;</tt></span><a href="#(part._.Introduction)" class="tocsubseclink" pltdoc="x">Introduction</a></td></tr><tr><td><span class="tocsublinknumber">2<tt>&nbsp;</tt></span><a href="#(part._.The_plan_of_attack)" class="tocsubseclink" pltdoc="x">The plan of attack</a></td></tr><tr><td><span class="tocsublinknumber">3<tt>&nbsp;</tt></span><a href="#(part._.Transformers)" class="tocsubseclink" pltdoc="x">Transformers</a></td></tr><tr><td><span class="tocsublinknumber">3.1<tt>&nbsp;</tt></span><a href="#(part._.What_is_a_syntax_transformer_)" class="tocsubseclink" pltdoc="x">What is a syntax transformer?</a></td></tr><tr><td><span class="tocsublinknumber">3.2<tt>&nbsp;</tt></span><a href="#(part._.What_is_the_input_)" class="tocsubseclink" pltdoc="x">What is the input?</a></td></tr><tr><td><span class="tocsublinknumber">3.3<tt>&nbsp;</tt></span><a href="#(part._.Actually_transforming_the_input)" class="tocsubseclink" pltdoc="x">Actually transforming the input</a></td></tr><tr><td><span class="tocsublinknumber">3.4<tt>&nbsp;</tt></span><a href="#(part._.Compile_time_vs__run_time)" class="tocsubseclink" pltdoc="x">Compile time vs. run time</a></td></tr><tr><td><span class="tocsublinknumber">4<tt>&nbsp;</tt></span><a href="#(part._.Pattern_matching__syntax-case_and_syntax-rules)" class="tocsubseclink" pltdoc="x">Pattern matching:<span class="mywbr"> </span> syntax-<wbr></wbr>case and syntax-<wbr></wbr>rules</a></td></tr><tr><td><span class="tocsublinknumber">4.1<tt>&nbsp;</tt></span><a href="#(part._.Patterns_and_templates)" class="tocsubseclink" pltdoc="x">Patterns and templates</a></td></tr><tr><td><span class="tocsublinknumber">4.1.1<tt>&nbsp;</tt></span><a href="#(part.__.A_pattern_variable_can_t_be_used_outside_of_a_template_)" class="tocsubseclink" pltdoc="x">"A pattern variable can&rsquo;t be used outside of a template"</a></td></tr><tr><td><span class="tocsublinknumber">5<tt>&nbsp;</tt></span><a href="#(part._.Syntax_parameters)" class="tocsubseclink" pltdoc="x">Syntax parameters</a></td></tr><tr><td><span class="tocsublinknumber">6<tt>&nbsp;</tt></span><a href="#(part._.Robust_macros__syntax-parse)" class="tocsubseclink" pltdoc="x">Robust macros:<span class="mywbr"> </span> syntax-<wbr></wbr>parse</a></td></tr><tr><td><span class="tocsublinknumber">7<tt>&nbsp;</tt></span><a href="#(part._.Other_questions)" class="tocsubseclink" pltdoc="x">Other questions</a></td></tr><tr><td><span class="tocsublinknumber">7.1<tt>&nbsp;</tt></span><a href="#(part._.What_s_the_point_of_with-syntax_)" class="tocsubseclink" pltdoc="x">What&rsquo;s the point of <span class="RktSym"><span class="RktStxLink">with-<wbr></wbr>syntax</span></span>?</a></td></tr><tr><td><span class="tocsublinknumber">7.2<tt>&nbsp;</tt></span><a href="#(part._.What_s_the_point_of_begin-for-syntax_)" class="tocsubseclink" pltdoc="x">What&rsquo;s the point of <span class="RktSym"><span class="RktStxLink">begin-<wbr></wbr>for-<wbr></wbr>syntax</span></span>?</a></td></tr><tr><td><span class="tocsublinknumber">7.3<tt>&nbsp;</tt></span><a href="#(part._.What_s_the_point_of_racket_splicing_)" class="tocsubseclink" pltdoc="x">What&rsquo;s the point of <span class="RktSym">racket/<span class="mywbr"> </span>splicing</span>?</a></td></tr><tr><td><span class="tocsublinknumber">8<tt>&nbsp;</tt></span><a href="#(part._.References_.Acknowledgments)" class="tocsubseclink" pltdoc="x">References/<span class="mywbr"> </span>Acknowledgments</a></td></tr><tr><td><span class="tocsublinknumber">9<tt>&nbsp;</tt></span><a href="#(part._.Epilogue)" class="tocsubseclink" pltdoc="x">Epilogue</a></td></tr></table></div></div><div class="maincolumn"><div class="main"><h2><a name="(part._.Fear_of_.Macros)"></a>Fear of Macros</h2><div class="SAuthorListBox"><span class="SAuthorList"><p class="author"><a href="https://github.com/greghendershott/fear-of-macros/issues">Greg Hendershott</a></p></span></div><p><div class="SIntrapara"><img src="fear-of-macros.jpg" alt="" /> </div><div class="SIntrapara"></div><div class="SIntrapara"><span class="Smaller">Copyright (c) 2012 by Greg Hendershott. All rights reserved.</span> -</div><div class="SIntrapara"><span class="Smaller">Last updated 2012-10-25 15:30:29</span></div><div class="SIntrapara"><table cellspacing="0"><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Introduction)" class="toptoclink" pltdoc="x">1<span class="hspace">&nbsp;</span>Introduction</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.The_plan_of_attack)" class="toptoclink" pltdoc="x">2<span class="hspace">&nbsp;</span>The plan of attack</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Transformers)" class="toptoclink" pltdoc="x">3<span class="hspace">&nbsp;</span>Transformers</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.What_is_a_syntax_transformer_)" class="toclink" pltdoc="x">3.1<span class="hspace">&nbsp;</span>What is a syntax transformer?</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.What_is_the_input_)" class="toclink" pltdoc="x">3.2<span class="hspace">&nbsp;</span>What is the input?</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Actually_transforming_the_input)" class="toclink" pltdoc="x">3.3<span class="hspace">&nbsp;</span>Actually transforming the input</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Compile_time_vs__run_time)" class="toclink" pltdoc="x">3.4<span class="hspace">&nbsp;</span>Compile time vs. run time</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Pattern_matching__syntax-case_and_syntax-rules)" class="toptoclink" pltdoc="x">4<span class="hspace">&nbsp;</span>Pattern matching: syntax-case and syntax-rules</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Patterns_and_templates)" class="toclink" pltdoc="x">4.1<span class="hspace">&nbsp;</span>Patterns and templates</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part.__.A_pattern_variable_can_t_be_used_outside_of_a_template_)" class="toclink" pltdoc="x">4.1.1<span class="hspace">&nbsp;</span>"A pattern variable can&rsquo;t be used outside of a template"</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Syntax_parameters)" class="toptoclink" pltdoc="x">5<span class="hspace">&nbsp;</span>Syntax parameters</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Robust_macros__syntax-parse)" class="toptoclink" pltdoc="x">6<span class="hspace">&nbsp;</span>Robust macros: syntax-parse</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Other_questions)" class="toptoclink" pltdoc="x">7<span class="hspace">&nbsp;</span>Other questions</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.What_s_the_point_of_with-syntax_)" class="toclink" pltdoc="x">7.1<span class="hspace">&nbsp;</span>What&rsquo;s the point of <span class="RktSym"><span class="RktStxLink">with-syntax</span></span>?</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.What_s_the_point_of_begin-for-syntax_)" class="toclink" pltdoc="x">7.2<span class="hspace">&nbsp;</span>What&rsquo;s the point of <span class="RktSym"><span class="RktStxLink">begin-for-syntax</span></span>?</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.What_s_the_point_of_racket_splicing_)" class="toclink" pltdoc="x">7.3<span class="hspace">&nbsp;</span>What&rsquo;s the point of <span class="RktSym">racket/splicing</span>?</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.References_.Acknowledgments)" class="toptoclink" pltdoc="x">8<span class="hspace">&nbsp;</span>References/Acknowledgments</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Epilogue)" class="toptoclink" pltdoc="x">9<span class="hspace">&nbsp;</span>Epilogue</a></p></td></tr></table></div></p><h3>1<tt>&nbsp;</tt><a name="(part._.Introduction)"></a>Introduction</h3><p>I learned Racket after 25 years of doing C/C++ imperative programming.</p><p>Some psychic whiplash resulted.</p><p>"All the parentheses" was actually not a big deal. Instead, the first +</div><div class="SIntrapara"><span class="Smaller">Last updated 2012-10-25 18:15:21</span></div><div class="SIntrapara"><table cellspacing="0"><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Introduction)" class="toptoclink" pltdoc="x">1<span class="hspace">&nbsp;</span>Introduction</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.The_plan_of_attack)" class="toptoclink" pltdoc="x">2<span class="hspace">&nbsp;</span>The plan of attack</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Transformers)" class="toptoclink" pltdoc="x">3<span class="hspace">&nbsp;</span>Transformers</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.What_is_a_syntax_transformer_)" class="toclink" pltdoc="x">3.1<span class="hspace">&nbsp;</span>What is a syntax transformer?</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.What_is_the_input_)" class="toclink" pltdoc="x">3.2<span class="hspace">&nbsp;</span>What is the input?</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Actually_transforming_the_input)" class="toclink" pltdoc="x">3.3<span class="hspace">&nbsp;</span>Actually transforming the input</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Compile_time_vs__run_time)" class="toclink" pltdoc="x">3.4<span class="hspace">&nbsp;</span>Compile time vs. run time</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Pattern_matching__syntax-case_and_syntax-rules)" class="toptoclink" pltdoc="x">4<span class="hspace">&nbsp;</span>Pattern matching: syntax-case and syntax-rules</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Patterns_and_templates)" class="toclink" pltdoc="x">4.1<span class="hspace">&nbsp;</span>Patterns and templates</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part.__.A_pattern_variable_can_t_be_used_outside_of_a_template_)" class="toclink" pltdoc="x">4.1.1<span class="hspace">&nbsp;</span>"A pattern variable can&rsquo;t be used outside of a template"</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Syntax_parameters)" class="toptoclink" pltdoc="x">5<span class="hspace">&nbsp;</span>Syntax parameters</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Robust_macros__syntax-parse)" class="toptoclink" pltdoc="x">6<span class="hspace">&nbsp;</span>Robust macros: syntax-parse</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Other_questions)" class="toptoclink" pltdoc="x">7<span class="hspace">&nbsp;</span>Other questions</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.What_s_the_point_of_with-syntax_)" class="toclink" pltdoc="x">7.1<span class="hspace">&nbsp;</span>What&rsquo;s the point of <span class="RktSym"><span class="RktStxLink">with-syntax</span></span>?</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.What_s_the_point_of_begin-for-syntax_)" class="toclink" pltdoc="x">7.2<span class="hspace">&nbsp;</span>What&rsquo;s the point of <span class="RktSym"><span class="RktStxLink">begin-for-syntax</span></span>?</a></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.What_s_the_point_of_racket_splicing_)" class="toclink" pltdoc="x">7.3<span class="hspace">&nbsp;</span>What&rsquo;s the point of <span class="RktSym">racket/splicing</span>?</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.References_.Acknowledgments)" class="toptoclink" pltdoc="x">8<span class="hspace">&nbsp;</span>References/Acknowledgments</a></p></td></tr><tr><td><p><span class="hspace"></span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><a href="#(part._.Epilogue)" class="toptoclink" pltdoc="x">9<span class="hspace">&nbsp;</span>Epilogue</a></p></td></tr></table></div></p><h3>1<tt>&nbsp;</tt><a name="(part._.Introduction)"></a>Introduction</h3><p>I learned Racket after 25 years of doing C/C++ imperative programming.</p><p>Some psychic whiplash resulted.</p><p>"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.</p><p>But two final frontiers remained: Macros and continuations.</p><p>I found that simple macros were easy and understandable, plus there @@ -184,29 +184,30 @@ converting from syntax to datum and back again.</p><p>Recap: If you want to mung <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stx-patterns.html#(form._((lib._racket%2Fprivate%2Fstxcase-scheme..rkt)._syntax))" class="RktStxLink" pltdoc="x">syntax</a></span> or <span class="stt">#</span><span class="stt">&rsquo;</span><span class="stt"></span> on the pattern variables to turn them into fun size templates, and often also use <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#(def._((quote._~23~25kernel)._syntax-~3edatum))" class="RktValLink" pltdoc="x">syntax-&gt;datum</a></span> to get the interesting value inside. Finally, <span class="RktSym">format-id</span> is -convenient for formatting identifier names.</p><h3>5<tt>&nbsp;</tt><a name="(part._.Syntax_parameters)"></a>Syntax parameters</h3><p>"Anaphoric if" or "aif" is a popular macro example. Instead of writing:</p><blockquote class="SCodeFlow"><table cellspacing="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket%2Fprivate%2Fletstx-scheme..rkt)._let))" class="RktStxLink" pltdoc="x">let</a></span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">tmp</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">big-long-calculation</span><span class="RktPn">)</span><span class="RktPn">]</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/if.html#(form._((quote._~23~25kernel)._if))" class="RktStxLink" pltdoc="x">if</a></span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktSym">tmp</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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">tmp</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktMeta"></span><span class="RktVal">#f</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr></table></blockquote><p>It would be great to write:</p><blockquote class="SCodeFlow"><table cellspacing="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">aif</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">big-long-calculation</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&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">it</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktMeta"></span><span class="RktVal">#f</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr></table></blockquote><p>In other words, when the condition is true, an <span class="RktSym">it</span> identifier +convenient for formatting identifier names.</p><h3>5<tt>&nbsp;</tt><a name="(part._.Syntax_parameters)"></a>Syntax parameters</h3><p>"Anaphoric if" or "aif" is a popular macro example. Instead of writing:</p><blockquote class="SCodeFlow"><table cellspacing="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket%2Fprivate%2Fletstx-scheme..rkt)._let))" class="RktStxLink" pltdoc="x">let</a></span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">tmp</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">big-long-calculation</span><span class="RktPn">)</span><span class="RktPn">]</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/if.html#(form._((quote._~23~25kernel)._if))" class="RktStxLink" pltdoc="x">if</a></span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktSym">tmp</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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">tmp</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktMeta"></span><span class="RktVal">#f</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr></table></blockquote><p>You could write:</p><blockquote class="SCodeFlow"><table cellspacing="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">aif</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">big-long-calculation</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&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">it</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktMeta"></span><span class="RktVal">#f</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr></table></blockquote><p>In other words, when the condition is true, an <span class="RktSym">it</span> identifier is automatically created and set to the value of the condition. This -should be easy:</p><blockquote class="SCodeFlow"><table cellspacing="0" class="RktBlk"><tr><td><table cellspacing="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/stx-patterns.html#(form._((lib._racket%2Fprivate%2Fmisc..rkt)._define-syntax-rule))" class="RktStxLink" pltdoc="x">define-syntax-rule</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">aif</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="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket%2Fprivate%2Fletstx-scheme..rkt)._let))" class="RktStxLink" pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">it</span><span class="hspace">&nbsp;</span><span class="RktSym">condition</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#(form._((quote._~23~25kernel)._if))" class="RktStxLink" pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktSym">it</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktSym">true-expr</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">aif</span><span class="hspace">&nbsp;</span><span class="RktVal">#t</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((lib._racket%2Fprivate%2Fmisc..rkt)._displayln))" class="RktValLink" pltdoc="x">displayln</a></span><span class="hspace">&nbsp;</span><span class="RktSym">it</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/void.html#(def._((quote._~23~25kernel)._void))" class="RktValLink" pltdoc="x">void</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">it: 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></table></blockquote><p>Wait, what&#8212;<wbr></wbr><span class="RktSym">it</span> is undefined?</p><p>It turns out that all along we have been protected from making a -certain kind of mistake in our macros. The mistake is to introduce a -variable that accidentally conflicts with one in the code that is -using our macro.</p><p>The Racket Reference -<a href="http://docs.racket-lang.org/reference/syntax-model.html#(part._transformer-model)">Section -1.2.3.5 Transformer Bindings.</a> has a good explanation of this, and an -example. (You can stop when you reach the part about set! -transformers.) Basically, the input syntax has "marks" to preserve -lexical scope. This makes your macro behave like a normal function. If -a normal function defines a variable named <span class="RktSym">x</span>, it won&rsquo;t -conflict with a variable named <span class="RktSym">x</span> in an outer scope.</p><p>This makes it easy to write reliable macros that behave -predictably. Unfortunately, once in awhile, we want to introduce a -magic variable like <span class="RktSym">it</span> for <span class="RktSym">aif</span> on purpose.</p><p>The way to do this is with <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxparam.html#(form._((lib._racket%2Fstxparam..rkt)._define-syntax-parameter))" class="RktStxLink" pltdoc="x">define-syntax-parameter</a></span> and +should be easy:</p><blockquote class="SCodeFlow"><table cellspacing="0" class="RktBlk"><tr><td><table cellspacing="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/stx-patterns.html#(form._((lib._racket%2Fprivate%2Fmisc..rkt)._define-syntax-rule))" class="RktStxLink" pltdoc="x">define-syntax-rule</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">aif</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="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket%2Fprivate%2Fletstx-scheme..rkt)._let))" class="RktStxLink" pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">it</span><span class="hspace">&nbsp;</span><span class="RktSym">condition</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#(form._((quote._~23~25kernel)._if))" class="RktStxLink" pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktSym">it</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktSym">true-expr</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">aif</span><span class="hspace">&nbsp;</span><span class="RktVal">#t</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((lib._racket%2Fprivate%2Fmisc..rkt)._displayln))" class="RktValLink" pltdoc="x">displayln</a></span><span class="hspace">&nbsp;</span><span class="RktSym">it</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/void.html#(def._((quote._~23~25kernel)._void))" class="RktValLink" pltdoc="x">void</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">it: 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></table></blockquote><p>Wait, what? <span class="RktSym">it</span> is undefined?</p><p>It turns out that all along we have been protected from making a +certain kind of mistake in our macros. The mistake is if our new +syntax introduces a variable that accidentally conflicts with one in +the code surrounding our macro.</p><p>The Racket <span style="font-style: italic">Reference</span> section, +<a href="http://docs.racket-lang.org/reference/syntax-model.html#(part._transformer-model)">Transformer +Bindings</a>, has a good explanation and example. Basically, syntax +has "marks" to preserve lexical scope. This makes your macro behave +like a normal function, for lexical scoping.</p><p>If a normal function defines a variable named <span class="RktSym">x</span>, it won&rsquo;t +conflict with a variable named <span class="RktSym">x</span> in an outer scope:</p><blockquote class="SCodeFlow"><table cellspacing="0" class="RktBlk"><tr><td><table cellspacing="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/let.html#(form._((lib._racket%2Fprivate%2Fletstx-scheme..rkt)._let))" class="RktStxLink" pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">x</span><span class="hspace">&nbsp;</span><span class="RktVal">"outer"</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket%2Fprivate%2Fletstx-scheme..rkt)._let))" class="RktStxLink" pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">x</span><span class="hspace">&nbsp;</span><span class="RktVal">"inner"</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((quote._~23~25kernel)._printf))" class="RktValLink" pltdoc="x">printf</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"The inner `x' is ~s\n"</span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((quote._~23~25kernel)._printf))" class="RktValLink" pltdoc="x">printf</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"The outer `x' is ~s\n"</span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><table cellspacing="0"><tr><td><p><span class="RktOut">The inner `x' is "inner"</span></p></td></tr><tr><td><p><span class="RktOut">The outer `x' is "outer"</span></p></td></tr></table></td></tr></table></blockquote><p>When your macros also respect lexical scoping, it&rsquo;s easy to write +reliable macros that behave predictably.</p><p>So that&rsquo;s wonderful default behavior. But <span style="font-style: italic">sometimes</span> we want +to introduce a magic variable on purpose&#8212;<wbr></wbr>such as <span class="RktSym">it</span> for +<span class="RktSym">aif</span>.</p><p>The way to do this is with a "syntax parameter", using +<span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxparam.html#(form._((lib._racket%2Fstxparam..rkt)._define-syntax-parameter))" class="RktStxLink" pltdoc="x">define-syntax-parameter</a></span> and <span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxparam.html#(form._((lib._racket%2Fstxparam..rkt)._syntax-parameterize))" class="RktStxLink" pltdoc="x">syntax-parameterize</a></span>. You&rsquo;re probably familiar with regular -parameters in Racket.</p><blockquote class="SCodeFlow"><table cellspacing="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#(form._((lib._racket%2Fprivate%2Fbase..rkt)._define))" class="RktStxLink" pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">current-foo</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/parameters.html#(def._((quote._~23~25kernel)._make-parameter))" class="RktValLink" pltdoc="x">make-parameter</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"some default value"</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">current-foo</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">"some default value"</span></p></td></tr><tr><td><table cellspacing="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/parameters.html#(form._((lib._racket%2Fprivate%2Fmore-scheme..rkt)._parameterize))" class="RktStxLink" pltdoc="x">parameterize</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">current-foo</span><span class="hspace">&nbsp;</span><span class="RktVal">"I have a new value, for now"</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">current-foo</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><p><span class="RktRes">"I have a new value, for now"</span></p></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">current-foo</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">"some default value"</span></p></td></tr></table></blockquote><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>Historically, there are other ways to do this. If you -know them, you will want to unlearn them. But if you&rsquo;re the target -audience I&rsquo;m writing for, you don&rsquo;t know them yet. You can skip -learning them now. (Someday if you want to understand someone else&rsquo;s -older macros, you can learn about them then.)</p></blockquote></blockquote></blockquote><p>The syntax variation of them works similarly. The idea is, we&rsquo;ll -define <span class="RktSym">it</span> to mean an error by default. Only inside of our -<span class="RktSym">aif</span> will it have a meaningful value:</p><blockquote class="SCodeFlow"><table cellspacing="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#(form._((lib._racket%2Fprivate%2Fbase..rkt)._require))" class="RktStxLink" pltdoc="x">require</a></span><span class="hspace">&nbsp;</span><span class="RktSym">racket/stxparam</span><span class="RktPn">)</span></td></tr><tr><td><table cellspacing="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/stxparam.html#(form._((lib._racket%2Fstxparam..rkt)._define-syntax-parameter))" class="RktStxLink" pltdoc="x">define-syntax-parameter</a></span><span class="hspace">&nbsp;</span><span class="RktSym">it</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/lambda.html#(form._((lib._racket%2Fprivate%2Fbase..rkt)._lambda))" class="RktStxLink" 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="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/exns.html#(def._((quote._~23~25kernel)._raise-syntax-error))" class="RktValLink" pltdoc="x">raise-syntax-error</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#(def._((quote._~23~25kernel)._syntax-e))" class="RktValLink" pltdoc="x">syntax-e</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktVal">"can only be used inside aif"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><table cellspacing="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/stx-patterns.html#(form._((lib._racket%2Fprivate%2Fmisc..rkt)._define-syntax-rule))" class="RktStxLink" pltdoc="x">define-syntax-rule</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">aif</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="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket%2Fprivate%2Fletstx-scheme..rkt)._let))" class="RktStxLink" pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">tmp</span><span class="hspace">&nbsp;</span><span class="RktSym">condition</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#(form._((quote._~23~25kernel)._if))" class="RktStxLink" pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktSym">tmp</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></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/stxparam.html#(form._((lib._racket%2Fstxparam..rkt)._syntax-parameterize))" class="RktStxLink" pltdoc="x">syntax-parameterize</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">it</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxtrans.html#(def._((quote._~23~25kernel)._make-rename-transformer))" class="RktValLink" pltdoc="x">make-rename-transformer</a></span><span class="hspace">&nbsp;</span><span class="RktRdr">#'</span><span class="RktSym">tmp</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktSym">true-expr</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">aif</span><span class="hspace">&nbsp;</span><span class="RktVal">10</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((lib._racket%2Fprivate%2Fmisc..rkt)._displayln))" class="RktValLink" pltdoc="x">displayln</a></span><span class="hspace">&nbsp;</span><span class="RktSym">it</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/void.html#(def._((quote._~23~25kernel)._void))" class="RktValLink" pltdoc="x">void</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktOut">10</span></p></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">aif</span><span class="hspace">&nbsp;</span><span class="RktVal">#f</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((lib._racket%2Fprivate%2Fmisc..rkt)._displayln))" class="RktValLink" pltdoc="x">displayln</a></span><span class="hspace">&nbsp;</span><span class="RktSym">it</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/void.html#(def._((quote._~23~25kernel)._void))" class="RktValLink" pltdoc="x">void</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>If we try to use <span class="RktSym">it</span> outside of an <span class="RktSym">aif</span> form, and +parameters in Racket:</p><blockquote class="SCodeFlow"><table cellspacing="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#(form._((lib._racket%2Fprivate%2Fbase..rkt)._define))" class="RktStxLink" pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">current-foo</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/parameters.html#(def._((quote._~23~25kernel)._make-parameter))" class="RktValLink" pltdoc="x">make-parameter</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"some default value"</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">current-foo</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">"some default value"</span></p></td></tr><tr><td><table cellspacing="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/parameters.html#(form._((lib._racket%2Fprivate%2Fmore-scheme..rkt)._parameterize))" class="RktStxLink" pltdoc="x">parameterize</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">current-foo</span><span class="hspace">&nbsp;</span><span class="RktVal">"I have a new value, for now"</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">current-foo</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><p><span class="RktRes">"I have a new value, for now"</span></p></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">current-foo</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">"some default value"</span></p></td></tr></table></blockquote><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>Historically, there are other ways to do this. If you&rsquo;re +the target audience I&rsquo;m writing for, you don&rsquo;t know them yet. I +suggest not bothering to learn them, yet. (Someday if you want to +understand someone else&rsquo;s older macros, you can learn about them +then.)</p></blockquote></blockquote></blockquote><p>That&rsquo;s a normal parameter. The syntax variation works similarly. The +idea is that we&rsquo;ll define <span class="RktSym">it</span> to mean an error by +default. Only inside of our <span class="RktSym">aif</span> will it have a meaningful +value:</p><blockquote class="SCodeFlow"><table cellspacing="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#(form._((lib._racket%2Fprivate%2Fbase..rkt)._require))" class="RktStxLink" pltdoc="x">require</a></span><span class="hspace">&nbsp;</span><span class="RktSym">racket/stxparam</span><span class="RktPn">)</span></td></tr><tr><td><table cellspacing="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/stxparam.html#(form._((lib._racket%2Fstxparam..rkt)._define-syntax-parameter))" class="RktStxLink" pltdoc="x">define-syntax-parameter</a></span><span class="hspace">&nbsp;</span><span class="RktSym">it</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/lambda.html#(form._((lib._racket%2Fprivate%2Fbase..rkt)._lambda))" class="RktStxLink" 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="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/exns.html#(def._((quote._~23~25kernel)._raise-syntax-error))" class="RktValLink" pltdoc="x">raise-syntax-error</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxops.html#(def._((quote._~23~25kernel)._syntax-e))" class="RktValLink" pltdoc="x">syntax-e</a></span><span class="hspace">&nbsp;</span><span class="RktSym">stx</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktVal">"can only be used inside aif"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><table cellspacing="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/stx-patterns.html#(form._((lib._racket%2Fprivate%2Fmisc..rkt)._define-syntax-rule))" class="RktStxLink" pltdoc="x">define-syntax-rule</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">aif</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="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket%2Fprivate%2Fletstx-scheme..rkt)._let))" class="RktStxLink" pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">tmp</span><span class="hspace">&nbsp;</span><span class="RktSym">condition</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/if.html#(form._((quote._~23~25kernel)._if))" class="RktStxLink" pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktSym">tmp</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></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/stxparam.html#(form._((lib._racket%2Fstxparam..rkt)._syntax-parameterize))" class="RktStxLink" pltdoc="x">syntax-parameterize</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">it</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/stxtrans.html#(def._((quote._~23~25kernel)._make-rename-transformer))" class="RktValLink" pltdoc="x">make-rename-transformer</a></span><span class="hspace">&nbsp;</span><span class="RktRdr">#'</span><span class="RktSym">tmp</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktSym">true-expr</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPlain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">aif</span><span class="hspace">&nbsp;</span><span class="RktVal">10</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((lib._racket%2Fprivate%2Fmisc..rkt)._displayln))" class="RktValLink" pltdoc="x">displayln</a></span><span class="hspace">&nbsp;</span><span class="RktSym">it</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/void.html#(def._((quote._~23~25kernel)._void))" class="RktValLink" pltdoc="x">void</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktOut">10</span></p></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">aif</span><span class="hspace">&nbsp;</span><span class="RktVal">#f</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((lib._racket%2Fprivate%2Fmisc..rkt)._displayln))" class="RktValLink" pltdoc="x">displayln</a></span><span class="hspace">&nbsp;</span><span class="RktSym">it</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/void.html#(def._((quote._~23~25kernel)._void))" class="RktValLink" pltdoc="x">void</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>If we try to use <span class="RktSym">it</span> outside of an <span class="RktSym">aif</span> form, and <span class="RktSym">it</span> isn&rsquo;t otherwise defined, we get an error like we want:</p><blockquote class="SCodeFlow"><table cellspacing="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/Writing.html#(def._((lib._racket%2Fprivate%2Fmisc..rkt)._displayln))" class="RktValLink" pltdoc="x">displayln</a></span><span class="hspace">&nbsp;</span><span class="RktSym">it</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">it: can only be used inside aif</span></p></td></tr></table></blockquote><p>But we can still define <span class="RktSym">it</span> as a normal variable:</p><blockquote class="SCodeFlow"><table cellspacing="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#(form._((lib._racket%2Fprivate%2Fbase..rkt)._define))" class="RktStxLink" pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">it</span><span class="hspace">&nbsp;</span><span class="RktVal">10</span><span class="RktPn">)</span></td></tr><tr><td><span class="stt">&gt; </span><span class="RktSym">it</span></td></tr><tr><td><p><span class="RktRes">10</span></p></td></tr></table></blockquote><h3>6<tt>&nbsp;</tt><a name="(part._.Robust_macros__syntax-parse)"></a>Robust macros: syntax-parse</h3><p>TO-DO. TO-DO. TO-DO.</p><h3>7<tt>&nbsp;</tt><a name="(part._.Other_questions)"></a>Other questions</h3><p>Hopefully I will answer these in the course of the other sections. But diff --git a/main.rkt b/main.rkt @@ -694,7 +694,7 @@ convenient for formatting identifier names. #f)) } -It would be great to write: +You could write: @codeblock{ (aif (big-long-calculation) @@ -716,29 +716,40 @@ should be easy: (aif #t (displayln it) (void)) ] -Wait, what---@racket[it] is undefined? +Wait, what? @racket[it] is undefined? It turns out that all along we have been protected from making a -certain kind of mistake in our macros. The mistake is to introduce a -variable that accidentally conflicts with one in the code that is -using our macro. - -The Racket Reference -@hyperlink["http://docs.racket-lang.org/reference/syntax-model.html#(part._transformer-model)" "Section -1.2.3.5 Transformer Bindings."] has a good explanation of this, and an -example. (You can stop when you reach the part about set! -transformers.) Basically, the input syntax has "marks" to preserve -lexical scope. This makes your macro behave like a normal function. If -a normal function defines a variable named @racket[x], it won't -conflict with a variable named @racket[x] in an outer scope. - -This makes it easy to write reliable macros that behave -predictably. Unfortunately, once in awhile, we want to introduce a -magic variable like @racket[it] for @racket[aif] on purpose. - -The way to do this is with @racket[define-syntax-parameter] and +certain kind of mistake in our macros. The mistake is if our new +syntax introduces a variable that accidentally conflicts with one in +the code surrounding our macro. + +The Racket @italic{Reference} section, +@hyperlink["http://docs.racket-lang.org/reference/syntax-model.html#(part._transformer-model)" "Transformer +Bindings"], has a good explanation and example. Basically, syntax +has "marks" to preserve lexical scope. This makes your macro behave +like a normal function, for lexical scoping. + +If a normal function defines a variable named @racket[x], it won't +conflict with a variable named @racket[x] in an outer scope: + +@i[ +(let ([x "outer"]) + (let ([x "inner"]) + (printf "The inner `x' is ~s\n" x)) + (printf "The outer `x' is ~s\n" x)) +] + +When your macros also respect lexical scoping, it's easy to write +reliable macros that behave predictably. + +So that's wonderful default behavior. But @italic{sometimes} we want +to introduce a magic variable on purpose---such as @racket[it] for +@racket[aif]. + +The way to do this is with a "syntax parameter", using +@racket[define-syntax-parameter] and @racket[syntax-parameterize]. You're probably familiar with regular -parameters in Racket. +parameters in Racket: @i[ (define current-foo (make-parameter "some default value")) @@ -748,15 +759,16 @@ parameters in Racket. (current-foo) ] -@margin-note{Historically, there are other ways to do this. If you -know them, you will want to unlearn them. But if you're the target -audience I'm writing for, you don't know them yet. You can skip -learning them now. (Someday if you want to understand someone else's -older macros, you can learn about them then.)} +@margin-note{Historically, there are other ways to do this. If you're +the target audience I'm writing for, you don't know them yet. I +suggest not bothering to learn them, yet. (Someday if you want to +understand someone else's older macros, you can learn about them +then.)} -The syntax variation of them works similarly. The idea is, we'll -define @racket[it] to mean an error by default. Only inside of our -@racket[aif] will it have a meaningful value: +That's a normal parameter. The syntax variation works similarly. The +idea is that we'll define @racket[it] to mean an error by +default. Only inside of our @racket[aif] will it have a meaningful +value: @i[ (require racket/stxparam)