fear-of-macros/Robust_macros__syntax-parse.html
Greg Hendershott d1af14bbea Gen htmls
2012-11-13 13:57:47 -05:00

31 lines
23 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta http-equiv="content-type" content="text-html; charset=utf-8" /><title>7&nbsp;Robust macros: syntax-parse</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]--><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" 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;);">&#9660;</a></td><td></td><td><a href="index.html" class="tocviewlink" 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" pltdoc="x">Preface</a></td></tr><tr><td align="right">2&nbsp;</td><td><a href="Our_plan_of_attack.html" class="tocviewlink" pltdoc="x">Our plan of attack</a></td></tr><tr><td align="right">3&nbsp;</td><td><a href="Transform_.html" class="tocviewlink" pltdoc="x">Transform!</a></td></tr><tr><td align="right">4&nbsp;</td><td><a href="pattern-matching.html" 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="Syntax_parameters.html" class="tocviewlink" 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" 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="" class="tocviewselflink" pltdoc="x">Robust macros:<span class="mywbr"> </span> syntax-<wbr></wbr>parse</a></td></tr><tr><td align="right">8&nbsp;</td><td><a href="References_and_Acknowledgments.html" class="tocviewlink" pltdoc="x">References and Acknowledgments</a></td></tr><tr><td align="right">9&nbsp;</td><td><a href="Epilogue.html" class="tocviewlink" 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>7&nbsp;</td><td><a href="" class="tocviewselflink" pltdoc="x">Robust macros:<span class="mywbr"> </span> syntax-<wbr></wbr>parse</a></td></tr></table><div class="tocviewsublistbottom" style="display: none;" id="tocview_1"><table cellspacing="0" cellpadding="0"><tr><td align="right">7.1&nbsp;</td><td><a href="#(part._.Error-handling_strategies_for_functions)" class="tocviewlink" pltdoc="x">Error-<wbr></wbr>handling strategies for functions</a></td></tr><tr><td align="right">7.2&nbsp;</td><td><a href="#(part._.Error-handling_strategies_for_macros)" class="tocviewlink" pltdoc="x">Error-<wbr></wbr>handling strategies for macros</a></td></tr><tr><td align="right">7.3&nbsp;</td><td><a href="#(part._.Using_syntax_parse)" class="tocviewlink" pltdoc="x">Using <span class="RktSym">syntax/<span class="mywbr"> </span>parse</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">7.1<tt>&nbsp;</tt></span><a href="#(part._.Error-handling_strategies_for_functions)" class="tocsubseclink" pltdoc="x">Error-<wbr></wbr>handling strategies for functions</a></td></tr><tr><td><span class="tocsublinknumber">7.2<tt>&nbsp;</tt></span><a href="#(part._.Error-handling_strategies_for_macros)" class="tocsubseclink" pltdoc="x">Error-<wbr></wbr>handling strategies for macros</a></td></tr><tr><td><span class="tocsublinknumber">7.3<tt>&nbsp;</tt></span><a href="#(part._.Using_syntax_parse)" class="tocsubseclink" pltdoc="x">Using <span class="RktSym">syntax/<span class="mywbr"> </span>parse</span></a></td></tr></table></div></div><div class="maincolumn"><div class="main"><div class="navsettop"><span class="navleft">&nbsp;&nbsp;</span><span class="navright"><a href="What_s_the_point_of_splicing-let_.html" title="backward to &quot;6 What's the point of splicing-let?&quot;" pltdoc="x">&larr; prev</a>&nbsp;&nbsp;<a href="index.html" title="up to &quot;Fear of Macros&quot;" pltdoc="x">up</a>&nbsp;&nbsp;<a href="References_and_Acknowledgments.html" title="forward to &quot;8 References and Acknowledgments&quot;" pltdoc="x">next &rarr;</a></span>&nbsp;</div><h3>7<tt>&nbsp;</tt><a name="(part._.Robust_macros__syntax-parse)"></a>Robust macros: syntax-parse</h3><p>Functions can be used in error. So can macros.</p><h4>7.1<tt>&nbsp;</tt><a name="(part._.Error-handling_strategies_for_functions)"></a>Error-handling strategies for functions</h4><p>With plain old functions, we have several choices how to handle
misuse.</p><p>1. Don&rsquo;t check at all.</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/define.html#(form._((lib._racket%2Fprivate%2Fbase..rkt)._define))" class="RktStxLink" pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">misuse</span><span class="hspace">&nbsp;</span><span class="RktSym">s</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/strings.html#(def._((quote._~23~25kernel)._string-append))" class="RktValLink" pltdoc="x">string-append</a></span><span class="hspace">&nbsp;</span><span class="RktSym">s</span><span class="hspace">&nbsp;</span><span class="RktVal">" snazzy suffix"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">User of the function:</span></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">misuse</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">string-append: contract violation</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">expected: string?</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">given: 0</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">argument position: 1st</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">other arguments...:</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;</span><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">" snazzy suffix"</span></p></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">I guess I goofed, but </span><span class="RktCmt">&ndash;</span><span class="RktCmt"> what is this "string-append" of which you</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">speak??</span></td></tr></table></blockquote><p>The problem is that the resulting error message will be confusing. Our
user thinks they&rsquo;re calling <span class="RktSym">misuse</span>, but is getting an error
message from <span class="RktSym"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((quote._~23~25kernel)._string-append))" class="RktValLink" pltdoc="x">string-append</a></span>. In this simple example they
could probably guess what&rsquo;s happening, but in most cases they won&rsquo;t.</p><p>2. Write some error handling code.</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/define.html#(form._((lib._racket%2Fprivate%2Fbase..rkt)._define))" class="RktStxLink" pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">misuse</span><span class="hspace">&nbsp;</span><span class="RktSym">s</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/when_unless.html#(form._((lib._racket%2Fprivate%2Fletstx-scheme..rkt)._unless))" class="RktStxLink" pltdoc="x">unless</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((quote._~23~25kernel)._string~3f))" class="RktValLink" pltdoc="x">string?</a></span><span class="hspace">&nbsp;</span><span class="RktSym">s</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)._error))" class="RktValLink" pltdoc="x">error</a></span><span class="hspace">&nbsp;</span><span class="RktVal">'</span><span class="RktVal">misuse</span><span class="hspace">&nbsp;</span><span class="RktVal">"expected a string, but got ~a"</span><span class="hspace">&nbsp;</span><span class="RktSym">s</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/strings.html#(def._((quote._~23~25kernel)._string-append))" class="RktValLink" pltdoc="x">string-append</a></span><span class="hspace">&nbsp;</span><span class="RktSym">s</span><span class="hspace">&nbsp;</span><span class="RktVal">" snazzy suffix"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">User of the function:</span></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">misuse</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">misuse: expected a string, but got 0</span></p></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">I goofed, and understand why! It</span><span class="RktCmt">'</span><span class="RktCmt">s a shame the writer of the</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">function had to work so hard to tell me.</span></td></tr></table></blockquote><p>Unfortunately the error code tends to overwhelm and/or obscure our
function definition. Also, the error message is good but not
great. Improving it would require even more error code.</p><p>3. Use a contract.</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/attaching-contracts-to-values.html#(form._((lib._racket%2Fcontract%2Fregion..rkt)._define%2Fcontract))" class="RktStxLink" pltdoc="x">define/contract</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">misuse</span><span class="hspace">&nbsp;</span><span class="RktSym">s</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/strings.html#(def._((quote._~23~25kernel)._string~3f))" class="RktValLink" pltdoc="x">string?</a></span><span class="hspace">&nbsp;</span><span class="RktPn">. </span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/function-contracts.html#(form._((lib._racket%2Fcontract%2Fbase..rkt)._-~3e))" class="RktStxLink" pltdoc="x"><span class="nobreak">-&gt;</span></a></span><span class="RktPn"> .</span><span class="hspace">&nbsp;</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((quote._~23~25kernel)._string~3f))" class="RktValLink" pltdoc="x">string?</a></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/strings.html#(def._((quote._~23~25kernel)._string-append))" class="RktValLink" pltdoc="x">string-append</a></span><span class="hspace">&nbsp;</span><span class="RktSym">s</span><span class="hspace">&nbsp;</span><span class="RktVal">" snazzy suffix"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">User of the function:</span></td></tr><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">misuse</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">misuse: contract violation</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">expected: string?, given: 0</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">in: the 1st argument of</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">(-&gt; string? string?)</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">contract from: (function misuse)</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">blaming: program</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">at: eval:130.0</span></p></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">I goofed, and understand why! I</span><span class="RktCmt">'</span><span class="RktCmt">m happier, and I hear the writer of</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt">&nbsp;</span><span class="RktCmt">the function is happier, too.</span></td></tr></table></blockquote><p>This is the best of both worlds.</p><p>The contract is a simple and concise. Even better, it&rsquo;s
declarative. We say what we want, without needing to spell out what to
do.</p><p>On the other hand the user of our function gets a very detailed error
message. Plus, the message is in a standard, familiar format.</p><p>4. Use Typed Racket.</p><p><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" class="RktBlk"><tr><td><span class="RktMeta">#lang</span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><a href="http://docs.racket-lang.org/ts-reference/index.html" class="RktModLink" pltdoc="x"><span class="RktSym">typed/racket</span></a><span class="RktMeta"></span></td></tr></table></blockquote></div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" class="RktBlk"><tr><td><span class="stt">&gt; </span><span class="RktPn">(</span><span class="RktSym">:</span><span class="hspace">&nbsp;</span><span class="RktSym">misuse</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">String</span><span class="hspace">&nbsp;</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/function-contracts.html#(form._((lib._racket%2Fcontract%2Fbase..rkt)._-~3e))" class="RktStxLink" pltdoc="x"><span class="nobreak">-&gt;</span></a></span><span class="hspace">&nbsp;</span><span class="RktSym">String</span><span class="RktPn">)</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/define.html#(form._((lib._racket%2Fprivate%2Fbase..rkt)._define))" class="RktStxLink" pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">misuse</span><span class="hspace">&nbsp;</span><span class="RktSym">s</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/strings.html#(def._((quote._~23~25kernel)._string-append))" class="RktValLink" pltdoc="x">string-append</a></span><span class="hspace">&nbsp;</span><span class="RktSym">s</span><span class="hspace">&nbsp;</span><span class="RktVal">" snazzy suffix"</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">misuse</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">eval:3:0: Type Checker: Expected String, but got Zero</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace">&nbsp;&nbsp;</span><span class="RktErr">in: (quote 0)</span></p></td></tr></table></blockquote></div></p><p>With respect to error handling, Typed Racket has the same benefits as
contracts. Good.</p><h4>7.2<tt>&nbsp;</tt><a name="(part._.Error-handling_strategies_for_macros)"></a>Error-handling strategies for macros</h4><p>For macros, we have similar choices.</p><p>1. Ignore the possibility of misuse. This choice is even worse for
macros. The default error messages are even less likely to make sense,
much less help our user know what to do.</p><p>2. Write error-handling code. We saw how much this complicated our
macros in our example of <a href="pattern-matching.html#(part._hash..refs)" pltdoc="x">Using dot notation for nested hash lookups</a>. And while we&rsquo;re still
learning how to write macros, we especially don&rsquo;t want more cognitive
load and obfuscation.</p><p>3. Use <span class="RktSym">syntax/parse</span>. For macros, this is the equivalent of
using contracts or types for functions. We can declare that input
pattern elements must be certain kinds of things, such as an
identifier. Instead of "types", the kinds are referred to as "syntax
classes". There are predefined syntax classes, plus we can define our
own.</p><h4>7.3<tt>&nbsp;</tt><a name="(part._.Using_syntax_parse)"></a>Using <span class="RktSym">syntax/parse</span></h4><p>November 1, 2012: So here&rsquo;s the deal. After writing everything up to
this point, I sat down to re-read the documentation for
<span class="RktSym">syntax/parse</span>. It was...very understandable. I didn&rsquo;t feel
confused.</p><blockquote class="SCodeFlow"><table cellspacing="0" class="RktBlk"><tr><td><span class="RktSym">&lt;span</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktSym">style=</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#(form._((quote._~23~25kernel)._quote))" class="RktStxLink" pltdoc="x">'</a></span><span class="RktSym">accent:</span><span class="RktMeta"></span><span class="hspace">&nbsp;</span><span class="RktMeta"></span><span class="RktVal">"Kenau-Reeves"</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#(form._((quote._~23~25kernel)._quote))" class="RktStxLink" pltdoc="x">'</a></span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._~3e))" class="RktValLink" pltdoc="x">&gt;</a></span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="RktSym">Whoa.</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="RktSym">&lt;/span&gt;</span><span class="RktMeta"></span></td></tr></table></blockquote><p>Why? The documentation is written very well. Also, everything up to
this point prepared me to appreciate what <span class="RktSym">syntax/parse</span> does,
and why. That leaves the "how" of using it, which seems pretty
straightforward, so far.</p><p>This might well be a temporary state of me "not knowing what I don&rsquo;t
know". As I dig in and use it more, maybe I&rsquo;ll discover something
confusing or tricky. If/when I do, I&rsquo;ll come back here and update
this.</p><p>But for now I&rsquo;ll focus on improving the previous parts.</p><div class="navsetbottom"><span class="navleft">&nbsp;&nbsp;</span><span class="navright"><a href="What_s_the_point_of_splicing-let_.html" title="backward to &quot;6 What's the point of splicing-let?&quot;" pltdoc="x">&larr; prev</a>&nbsp;&nbsp;<a href="index.html" title="up to &quot;Fear of Macros&quot;" pltdoc="x">up</a>&nbsp;&nbsp;<a href="References_and_Acknowledgments.html" title="forward to &quot;8 References and Acknowledgments&quot;" pltdoc="x">next &rarr;</a></span>&nbsp;</div></div></div><div id="contextindicator">&nbsp;</div></body></html>