/usr/share/doc/racket/syntax/stxparse-intro.html is in racket-doc 6.1-4.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | <!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>1.1 Introduction</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="../doc-site.css" title="default"/><script type="text/javascript" src="../scribble-common.js"></script><script type="text/javascript" src="../manual-racket.js"></script><script type="text/javascript" src="../doc-site.js"></script><script type="text/javascript" src="../local-redirect/local-redirect.js"></script><script type="text/javascript" src="../local-redirect/local-user-redirect.js"></script><!--[if IE 6]><style type="text/css">.SIEHidden { overflow: hidden; }</style><![endif]--></head><body id="doc-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,"tocview_0");">►</a></td><td></td><td><a href="index.html" class="tocviewlink" data-pltdoc="x">Syntax:<span class="mywbr"> </span> Meta-<wbr></wbr>Programming Helpers</a></td></tr></table></div><div class="tocviewsublisttop" style="display: none;" id="tocview_0"><table cellspacing="0" cellpadding="0"><tr><td align="right">1 </td><td><a href="stxparse.html" class="tocviewselflink" data-pltdoc="x">Parsing and Specifying Syntax</a></td></tr><tr><td align="right">2 </td><td><a href="syntax-helpers.html" class="tocviewlink" data-pltdoc="x">Syntax Object Helpers</a></td></tr><tr><td align="right">3 </td><td><a href="Datum_Pattern_Matching.html" class="tocviewlink" data-pltdoc="x">Datum Pattern Matching</a></td></tr><tr><td align="right">4 </td><td><a href="module-helpers.html" class="tocviewlink" data-pltdoc="x">Module-<wbr></wbr>Processing Helpers</a></td></tr><tr><td align="right">5 </td><td><a href="transformer-helpers.html" class="tocviewlink" data-pltdoc="x">Macro Transformer Helpers</a></td></tr><tr><td align="right">6 </td><td><a href="reader-helpers.html" class="tocviewlink" data-pltdoc="x">Reader Helpers</a></td></tr><tr><td align="right">7 </td><td><a href="Parsing_for_Bodies.html" class="tocviewlink" data-pltdoc="x">Parsing <span class="RktSym"><span class="RktStxLink">for</span></span> Bodies</a></td></tr><tr><td align="right">8 </td><td><a href="Unsafe_for_Clause_Transforms.html" class="tocviewlink" data-pltdoc="x">Unsafe <span class="RktSym"><span class="RktStxLink">for</span></span> Clause Transforms</a></td></tr><tr><td align="right">9 </td><td><a href="Source_Locations.html" class="tocviewlink" data-pltdoc="x">Source Locations</a></td></tr><tr><td align="right">10 </td><td><a href="Preserving_Source_Locations.html" class="tocviewlink" data-pltdoc="x">Preserving Source Locations</a></td></tr><tr><td align="right">11 </td><td><a href="toplevel.html" class="tocviewlink" data-pltdoc="x">Non-<wbr></wbr>Module Compilation And Expansion</a></td></tr><tr><td align="right">12 </td><td><a href="trusted-xforms.html" class="tocviewlink" data-pltdoc="x">Trusting Standard Recertifying Transformers</a></td></tr><tr><td align="right">13 </td><td><a href="docprovide.html" class="tocviewlink" data-pltdoc="x">Attaching Documentation to Exports</a></td></tr><tr><td align="right"></td><td><a href="doc-index.html" class="tocviewlink" data-pltdoc="x">Index</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,"tocview_1");">▼</a></td><td>1 </td><td><a href="stxparse.html" class="tocviewlink" data-pltdoc="x">Parsing and Specifying Syntax</a></td></tr></table><div class="tocviewsublistbottom" style="display: block;" id="tocview_1"><table cellspacing="0" cellpadding="0"><tr><td align="right">1.1 </td><td><a href="" class="tocviewselflink" data-pltdoc="x">Introduction</a></td></tr><tr><td align="right">1.2 </td><td><a href="stxparse-examples.html" class="tocviewlink" data-pltdoc="x">Examples</a></td></tr><tr><td align="right">1.3 </td><td><a href="Parsing_Syntax.html" class="tocviewlink" data-pltdoc="x">Parsing Syntax</a></td></tr><tr><td align="right">1.4 </td><td><a href="stxparse-specifying.html" class="tocviewlink" data-pltdoc="x">Specifying Syntax with Syntax Classes</a></td></tr><tr><td align="right">1.5 </td><td><a href="stxparse-patterns.html" class="tocviewlink" data-pltdoc="x">Syntax Patterns</a></td></tr><tr><td align="right">1.6 </td><td><a href="Defining_Simple_Macros.html" class="tocviewlink" data-pltdoc="x">Defining Simple Macros</a></td></tr><tr><td align="right">1.7 </td><td><a href="Literal_Sets_and_Conventions.html" class="tocviewlink" data-pltdoc="x">Literal Sets and Conventions</a></td></tr><tr><td align="right">1.8 </td><td><a href="Library_Syntax_Classes_and_Literal_Sets.html" class="tocviewlink" data-pltdoc="x">Library Syntax Classes and Literal Sets</a></td></tr><tr><td align="right">1.9 </td><td><a href="Debugging_and_Inspection_Tools.html" class="tocviewlink" data-pltdoc="x">Debugging and Inspection Tools</a></td></tr><tr><td align="right">1.10 </td><td><a href="Experimental.html" class="tocviewlink" data-pltdoc="x">Experimental</a></td></tr></table></div></div></div></div><div class="maincolumn"><div class="main"><div class="navsettop"><span class="navleft"><form class="searchform"><input class="searchbox" style="color: #888;" type="text" value="...search manuals..." title="Enter a search string to search the manuals" onkeypress="return DoSearchKey(event, this, "6.1", "../");" onfocus="this.style.color="black"; this.style.textAlign="left"; if (this.value == "...search manuals...") this.value="";" onblur="if (this.value.match(/^ *$/)) { this.style.color="#888"; this.style.textAlign="center"; this.value="...search manuals..."; }"/></form> <a href="../index.html" title="up to the documentation top" data-pltdoc="x" onclick="return GotoPLTRoot("6.1");">top</a></span><span class="navright"> <a href="stxparse.html" title="backward to "1 Parsing and Specifying Syntax"" data-pltdoc="x">← prev</a> <a href="stxparse.html" title="up to "1 Parsing and Specifying Syntax"" data-pltdoc="x">up</a> <a href="stxparse-examples.html" title="forward to "1.2 Examples"" data-pltdoc="x">next →</a></span> </div><h4 x-source-module="(lib "syntax/scribblings/syntax.scrbl")" x-part-tag=""stxparse-intro"">1.1<tt> </tt><a name="(part._stxparse-intro)"></a>Introduction</h4><p>This section provides an introduction to writing robust macros with
<span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span> and syntax classes.</p><p>As a running example we use the following task: write a macro named
<span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span> that has the same syntax and behavior as Racket’s
<span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">let</a></span> form. The macro should produce good error messages when
used incorrectly.</p><p>Here is the specification of <span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span>’s syntax:</p><blockquote class="leftindent"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0" class="boxed RBoxed"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><a name="(form._((lib._syntax/scribblings/parse/parse-dummy-bindings..rkt)._mylet))"></a><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxDef RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktVar">var-id</span><span class="hspace"> </span><span class="RktVar">rhs-expr</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktMeta">...</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVar">body</span><span class="hspace"> </span><span class="RktMeta"><a href="stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._......%2B%29%29" class="RktStxLink" data-pltdoc="x">...+</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktVar">loop-id</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktVar">var-id</span><span class="hspace"> </span><span class="RktVar">rhs-expr</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktMeta">...</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVar">body</span><span class="hspace"> </span><span class="RktMeta"><a href="stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._......%2B%29%29" class="RktStxLink" data-pltdoc="x">...+</a></span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote></blockquote><p>For simplicity, we handle only the first case for now. We return to
the second case later in the introduction.</p><p>The macro can be implemented very simply using
<span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fmisc..rkt%2529._define-syntax-rule%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">define-syntax-rule</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">> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fmisc..rkt%2529._define-syntax-rule%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">define-syntax-rule</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">var</span><span class="hspace"> </span><span class="RktSym">rhs</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">rhs</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote><p>When used correctly, the macro works, but it behaves very badly in the
presence of errors. In some cases, the macro merely fails with an
uninformative error message; in others, it blithely accepts illegal
syntax and passes it along to <span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span>, with strange
consequences:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">b</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">3</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">b</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">b</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: use does not match pattern: (mylet ((var rhs) ...)</span></p></td></tr><tr><td><p><span class="RktErr">body ...) at: (mylet (b 2) (sub1 b))</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._add1%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">add1</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">lambda: not an identifier, identifier with default, or</span></p></td></tr><tr><td><p><span class="RktErr">keyword at: 1</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktPn">#:x</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">y</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktSym">y</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">eval:2:0: arity mismatch;</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">the expected number of arguments does not match the given</span></p></td></tr><tr><td><p><span class="RktErr">number</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">expected: 0 plus an argument with keyword #:x</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">given: 2</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">arguments...:</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">1</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">2</span></p></td></tr></table></blockquote><p>These examples of illegal syntax are not to suggest that a typical
programmer would make such mistakes attempting to use
<span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span>. At least, not often, not after an initial learning
curve. But macros are also used by inexpert programmers and as targets
of other macros (or code generators), and many macros are far more
complex than <span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span>. Macros must validate their syntax and
report appropriate errors. Furthermore, the macro writer benefits from
the <span style="font-style: italic">machine-checked</span> specification of syntax in the form of more
readable, maintainable code.</p><p>We can improve the error behavior of the macro by using
<span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span>. First, we import <span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span> into the
<a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=syntax-model.html%23%2528tech._transformer._environment%2529&version=6.1" class="techoutside Sq" data-pltdoc="x"><span class="techinside">transformer environment</span></a>,
since we will use it to implement a macro transformer.</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._require%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">require</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._for-syntax%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">for-syntax</a></span><span class="hspace"> </span><span class="RktSym">syntax/parse</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>The following is the syntax specification above transliterated into a
<span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span> macro definition. It behaves no better than the
version using <span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fmisc..rkt%2529._define-syntax-rule%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">define-syntax-rule</a></span> above.</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">> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define-syntax%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">define-syntax</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span><span class="hspace"> </span><span class="RktSym">stx</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529.__%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">_</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">var-id</span><span class="hspace"> </span><span class="RktSym">rhs-expr</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._......%2B%29%29" class="RktStxLink" data-pltdoc="x">...+</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">var-id</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">rhs-expr</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></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>One minor difference is the use of <span class="RktSym"><a href="stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._......%2B%29%29" class="RktStxLink" data-pltdoc="x">...+</a></span> in the pattern;
<span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span> means match zero or more repetitions of the preceding
pattern; <span class="RktSym"><a href="stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._......%2B%29%29" class="RktStxLink" data-pltdoc="x">...+</a></span> means match one or more. Only <span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span> may
be used in the template, however.</p><p>The first step toward validation and high-quality error reporting is
annotating each of the macro’s pattern variables with the <a href="stxparse-specifying.html#%28tech._syntax._clas%29" class="techoutside" data-pltdoc="x"><span class="techinside">syntax
class</span></a> that describes its acceptable syntax. In <span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span>, each
variable must be an <span class="RktSym"><a href="Library_Syntax_Classes_and_Literal_Sets.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._identifier%29%29" class="RktStxLink" data-pltdoc="x">identifier</a></span> (<span class="RktSym"><a href="Library_Syntax_Classes_and_Literal_Sets.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._id%29%29" class="RktStxLink" data-pltdoc="x">id</a></span> for short) and
each right-hand side must be an <span class="RktSym"><a href="Library_Syntax_Classes_and_Literal_Sets.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._expr%29%29" class="RktStxLink" data-pltdoc="x">expr</a></span> (expression). An
<a href="stxparse-patterns.html#%28tech._annotated._pattern._variable%29" class="techoutside" data-pltdoc="x"><span class="techinside">annotated pattern variable</span></a> is written by concatenating the
pattern variable name, a colon character, and the syntax class
name.<span class="refelem"><span class="refcolumn"><span class="refcontent">For an alternative to the “colon” syntax, see the
<span class="RktSym"><a href="stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._~7evar%29%29" class="RktStxLink" data-pltdoc="x">~var</a></span> pattern form.</span></span></span></p><p><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">> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define-syntax%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">define-syntax</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span><span class="hspace"> </span><span class="RktSym">stx</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529.__%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">_</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym">var:id</span><span class="hspace"> </span><span class="RktSym">rhs:expr</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._......%2B%29%29" class="RktStxLink" data-pltdoc="x">...+</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">rhs</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote></div><div class="SIntrapara">Note that the syntax class annotations do not appear in the template
(i.e., <span class="RktSym">var</span>, not <span class="RktSym">var:id</span>).</div></p><p><div class="SIntrapara">The syntax class annotations are checked when we use the macro.
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">b</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">3</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._add1%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">add1</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected identifier at: "a"</span></p></td></tr></table></blockquote></div><div class="SIntrapara">The <span class="RktSym"><a href="Library_Syntax_Classes_and_Literal_Sets.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._expr%29%29" class="RktStxLink" data-pltdoc="x">expr</a></span> syntax class does not actually check that the term
it matches is a valid expression—<wbr></wbr>that would require calling that
macro expander. Instead, <span class="RktSym"><a href="Library_Syntax_Classes_and_Literal_Sets.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._expr%29%29" class="RktStxLink" data-pltdoc="x">expr</a></span> just means not a keyword.
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktPn">#:whoops</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected expression at: #:whoops</span></p></td></tr></table></blockquote></div><div class="SIntrapara">Also, <span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span> knows how to report a few kinds of errors
without any help:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: unexpected term at: 2</span></p></td></tr></table></blockquote></div><div class="SIntrapara">There are other kinds of errors, however, that this macro does not
handle gracefully:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: bad syntax at: (mylet (a 1) (+ a 2))</span></p></td></tr></table></blockquote></div><div class="SIntrapara">It’s too much to ask for the macro to respond, “This expression is
missing a pair of parentheses around <span class="RktPn">(</span><span class="RktSym">a</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">)</span>.” The pattern
matcher is not that smart. But it can pinpoint the source of the
error: when it encountered <span class="RktSym">a</span> it was expecting what we might
call a “binding pair,” but that term is not in its vocabulary yet.</div></p><p>To allow <span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span> to synthesize better errors, we must
attach <span style="font-style: italic">descriptions</span> to the patterns we recognize as discrete
syntactic categories. One way of doing that is by defining new syntax
classes:<span class="refelem"><span class="refcolumn"><span class="refcontent">Another way is the <span class="RktSym"><a href="stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._~7edescribe%29%29" class="RktStxLink" data-pltdoc="x">~describe</a></span> pattern
form.</span></span></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">> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define-syntax%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">define-syntax</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="stxparse-specifying.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._define-syntax-class%29%29" class="RktStxLink" data-pltdoc="x">define-syntax-class</a></span><span class="hspace"> </span><span class="RktSym">binding</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">#:description</span><span class="hspace"> </span><span class="RktVal">"binding pair"</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="stxparse-specifying.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._pattern%29%29" class="RktStxLink" data-pltdoc="x">pattern</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">var:id</span><span class="hspace"> </span><span class="RktSym">rhs:expr</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span><span class="hspace"> </span><span class="RktSym">stx</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529.__%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">_</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">b:binding</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._......%2B%29%29" class="RktStxLink" data-pltdoc="x">...+</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">b.var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">b.rhs</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></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>Note that we write <span class="RktSym">b.var</span> and <span class="RktSym">b.rhs</span> now. They are the
<a href="stxparse-patterns.html#%28tech._nested._attribute%29" class="techoutside" data-pltdoc="x"><span class="techinside">nested attributes</span></a> formed from the annotated pattern variable
<span class="RktSym">b</span> and the attributes <span class="RktSym">var</span> and <span class="RktSym">rhs</span> of the
syntax class <span class="RktSym">binding</span>.</p><p><div class="SIntrapara">Now the error messages can talk about “binding pairs.”
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected binding pair at: a</span></p></td></tr></table></blockquote></div><div class="SIntrapara">Errors are still reported in more specific terms when possible:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected identifier</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing binding pair at: "a"</span></p></td></tr></table></blockquote></div></p><p><div class="SIntrapara">There is one other constraint on the legal syntax of
<span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span>. The variables bound by the different binding pairs
must be distinct. Otherwise the macro creates an illegal
<span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span> form:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">lambda: duplicate argument name at: a</span></p></td></tr></table></blockquote></div></p><p><div class="SIntrapara">Constraints such as the distinctness requirement are expressed as side
conditions, thus:
</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">> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define-syntax%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">define-syntax</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="stxparse-specifying.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._define-syntax-class%29%29" class="RktStxLink" data-pltdoc="x">define-syntax-class</a></span><span class="hspace"> </span><span class="RktSym">binding</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">#:description</span><span class="hspace"> </span><span class="RktVal">"binding pair"</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="stxparse-specifying.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._pattern%29%29" class="RktStxLink" data-pltdoc="x">pattern</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">var:id</span><span class="hspace"> </span><span class="RktSym">rhs:expr</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span><span class="hspace"> </span><span class="RktSym">stx</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529.__%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">_</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">b:binding</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._......%2B%29%29" class="RktStxLink" data-pltdoc="x">...+</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">#:fail-when</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stxcmp.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._check-duplicate-identifier%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">check-duplicate-identifier</a></span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stxops.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._syntax-%7E3elist%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">syntax->list</a></span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktSym">b.var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktVal">"duplicate variable name"</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">b.var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">b.rhs</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote></div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: duplicate variable name at: a</span></p></td></tr></table></blockquote></div><div class="SIntrapara">The <span class="RktPn">#:fail-when</span> keyword is followed by two expressions: the
condition and the error message. When the condition evaluates to
anything but <span class="RktVal">#f</span>, the pattern fails. Additionally, if the
condition evaluates to a syntax object, that syntax object is used to
pinpoint the cause of the failure.</div></p><p><div class="SIntrapara">Syntax classes can have side conditions, too. Here is the macro
rewritten to include another syntax class representing a “sequence of
distinct binding pairs.”
</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">> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define-syntax%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">define-syntax</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="stxparse-specifying.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._define-syntax-class%29%29" class="RktStxLink" data-pltdoc="x">define-syntax-class</a></span><span class="hspace"> </span><span class="RktSym">binding</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">#:description</span><span class="hspace"> </span><span class="RktVal">"binding pair"</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="stxparse-specifying.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._pattern%29%29" class="RktStxLink" data-pltdoc="x">pattern</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">var:id</span><span class="hspace"> </span><span class="RktSym">rhs:expr</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="stxparse-specifying.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._define-syntax-class%29%29" class="RktStxLink" data-pltdoc="x">define-syntax-class</a></span><span class="hspace"> </span><span class="RktSym">distinct-bindings</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">#:description</span><span class="hspace"> </span><span class="RktVal">"sequence of distinct binding pairs"</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="stxparse-specifying.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._pattern%29%29" class="RktStxLink" data-pltdoc="x">pattern</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">b:binding</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">#:fail-when</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stxcmp.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._check-duplicate-identifier%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">check-duplicate-identifier</a></span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stxops.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._syntax-%7E3elist%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">syntax->list</a></span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktSym">b.var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktVal">"duplicate variable name"</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">#:with</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktSym">b.var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">#:with</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">rhs</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktSym">b.rhs</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span><span class="hspace"> </span><span class="RktSym">stx</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529.__%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">_</a></span><span class="hspace"> </span><span class="RktSym">bs:distinct-bindings</span><span class="hspace"> </span><span class="RktPn">. </span><span class="RktSym">body</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bs.var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">. </span><span class="RktSym">body</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">bs.rhs</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote></div><div class="SIntrapara">Here we’ve introduced the <span class="RktPn">#:with</span> clause. A <span class="RktPn">#:with</span>
clause matches a pattern with a computed term. Here we use it to bind
<span class="RktSym">var</span> and <span class="RktSym">rhs</span> as attributes of
<span class="RktSym">distinct-bindings</span>. By default, a syntax class only exports
its patterns’ pattern variables as attributes, not their nested
attributes.<span class="refelem"><span class="refcolumn"><span class="refcontent">The alternative would be to explicitly declare
the attributes of <span class="RktSym">distinct-bindings</span> to include the nested
attributes <span class="RktSym">b.var</span> and <span class="RktSym">b.rhs</span>, using the
<span class="RktPn">#:attribute</span> option. Then the macro would refer to
<span class="RktSym">bs.b.var</span> and <span class="RktSym">bs.b.rhs</span>.</span></span></span></div></p><p>Alas, so far the macro only implements half of the functionality
offered by Racket’s <span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">let</a></span>. We must add the
“named-<span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">let</a></span>” form. That turns out to be as simple as adding
a new clause:</p><p><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">> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define-syntax%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">define-syntax</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktSym">stx</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="stxparse-specifying.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._define-syntax-class%29%29" class="RktStxLink" data-pltdoc="x">define-syntax-class</a></span><span class="hspace"> </span><span class="RktSym">binding</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">#:description</span><span class="hspace"> </span><span class="RktVal">"binding pair"</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="stxparse-specifying.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._pattern%29%29" class="RktStxLink" data-pltdoc="x">pattern</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">var:id</span><span class="hspace"> </span><span class="RktSym">rhs:expr</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="stxparse-specifying.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._define-syntax-class%29%29" class="RktStxLink" data-pltdoc="x">define-syntax-class</a></span><span class="hspace"> </span><span class="RktSym">distinct-bindings</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">#:description</span><span class="hspace"> </span><span class="RktVal">"sequence of distinct binding pairs"</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="stxparse-specifying.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._pattern%29%29" class="RktStxLink" data-pltdoc="x">pattern</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">b:binding</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">#:fail-when</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stxcmp.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._check-duplicate-identifier%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">check-duplicate-identifier</a></span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stxops.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._syntax-%7E3elist%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">syntax->list</a></span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktSym">b.var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktVal">"duplicate variable name"</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">#:with</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktSym">b.var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">#:with</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">rhs</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktSym">b.rhs</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span><span class="hspace"> </span><span class="RktSym">stx</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529.__%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">_</a></span><span class="hspace"> </span><span class="RktSym">bs:distinct-bindings</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._......%2B%29%29" class="RktStxLink" data-pltdoc="x">...+</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bs.var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">bs.rhs</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529.__%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">_</a></span><span class="hspace"> </span><span class="RktSym">loop:id</span><span class="hspace"> </span><span class="RktSym">bs:distinct-bindings</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="stxparse-patterns.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._......%2B%29%29" class="RktStxLink" data-pltdoc="x">...+</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktRdr">#'</span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">letrec</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bs.var</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktSym">bs.rhs</span><span class="hspace"> </span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">...</a></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></table></blockquote></div><div class="SIntrapara">We are able to reuse the <span class="RktSym">distinct-bindings</span> syntax class, so
the addition of the “named-<span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">let</a></span>” syntax requires only three
lines.</div></p><p><div class="SIntrapara">But does adding this new case affect <span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span>’s ability
to pinpoint and report errors?
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">b</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">3</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._add1%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">add1</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected identifier</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing binding pair</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing sequence of distinct binding pairs at: "a"</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktPn">#:whoops</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected expression</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing binding pair</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing sequence of distinct binding pairs at:</span></p></td></tr><tr><td><p><span class="RktErr">#:whoops</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: unexpected term</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing binding pair</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing sequence of distinct binding pairs at: 2</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected binding pair</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing sequence of distinct binding pairs at: a</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: duplicate variable name</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing sequence of distinct binding pairs at: a</span></p></td></tr></table></blockquote></div><div class="SIntrapara">The error reporting for the original syntax seems intact. We should
verify that the named-<span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">let</a></span> syntax is working, that
<span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span> is not simply ignoring that clause.
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">b</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">3</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._add1%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">add1</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected identifier</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing binding pair</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing sequence of distinct binding pairs at: "a"</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktPn">#:whoops</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected expression</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing binding pair</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing sequence of distinct binding pairs at:</span></p></td></tr><tr><td><p><span class="RktErr">#:whoops</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: unexpected term</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing binding pair</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing sequence of distinct binding pairs at: 2</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected binding pair</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing sequence of distinct binding pairs at: a</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: duplicate variable name</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing sequence of distinct binding pairs at: a</span></p></td></tr></table></blockquote></div></p><p>How does <span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span> decide which clause the programmer was
attempting, so it can use it as a basis for error reporting? After
all, each of the bad uses of the named-<span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=6.1" class="RktStxLink Sq" data-pltdoc="x">let</a></span> syntax are also
bad uses of the normal syntax, and vice versa. And yet the macro doen
not produce errors like “<span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span>: expected sequence of
distinct binding pairs at: <span class="RktSym">loop</span>.”</p><p>The answer is that <span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span> records a list of all the
potential errors (including ones like <span class="RktSym">loop</span> not matching
<span class="RktSym">distinct-binding</span>) along with the <span style="font-style: italic">progress</span> made before
each error. Only the error with the most progress is reported.</p><p><div class="SIntrapara">For example, in this bad use of the macro,
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._add1%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">add1</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected identifier</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing binding pair</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing sequence of distinct binding pairs at: "a"</span></p></td></tr></table></blockquote></div><div class="SIntrapara">there are two potential errors: expected <span class="RktSym">distinct-bindings</span> at
<span class="RktSym">loop</span> and expected <span class="RktSym"><a href="Library_Syntax_Classes_and_Literal_Sets.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._identifier%29%29" class="RktStxLink" data-pltdoc="x">identifier</a></span> at <span class="RktVal">"a"</span>. The
second error occurs further in the term than the first, so it is
reported.</div></p><p><div class="SIntrapara">For another example, consider this term:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._add1%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">add1</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected identifier</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing binding pair</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing sequence of distinct binding pairs at: "a"</span></p></td></tr></table></blockquote></div><div class="SIntrapara">Again, there are two potential errors: expected <span class="RktSym"><a href="Library_Syntax_Classes_and_Literal_Sets.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._identifier%29%29" class="RktStxLink" data-pltdoc="x">identifier</a></span> at
<span class="RktPn">(</span><span class="RktPn">[</span><span class="RktVal">"a"</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="RktPn">)</span> and expected <span class="RktSym"><a href="Library_Syntax_Classes_and_Literal_Sets.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._identifier%29%29" class="RktStxLink" data-pltdoc="x">identifier</a></span> at
<span class="RktVal">"a"</span>. They both occur at the second term (or first argument,
if you prefer), but the second error occurs deeper in the
term. Progress is based on a left-to-right traversal of the syntax.</div></p><p><div class="SIntrapara">A final example: consider the following:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="http://download.racket-lang.org/docs/6.1/html/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=6.1" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: duplicate variable name</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">parsing context: </span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">while parsing sequence of distinct binding pairs at: a</span></p></td></tr></table></blockquote></div><div class="SIntrapara">There are two errors again: duplicate variable name at <span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="stt"> </span><span class="RktPn">[</span><span class="RktSym">a</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span> and expected <span class="RktSym"><a href="Library_Syntax_Classes_and_Literal_Sets.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._identifier%29%29" class="RktStxLink" data-pltdoc="x">identifier</a></span> at <span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">a</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="stt"> </span><span class="RktPn">[</span><span class="RktSym">a</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktPn">]</span><span class="RktPn">)</span>. Note that as far as <span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span> is concerned, the
progress associated with the duplicate error message is the second
term (first argument), not the second occurrence of <span class="RktSym">a</span>. That’s
because the check is associated with the entire
<span class="RktSym">distinct-bindings</span> pattern. It would seem that both errors
have the same progress, and yet only the first one is reported. The
difference between the two is that the first error is from a
<span style="font-style: italic">post-traversal</span> check, whereas the second is from a normal
(i.e., pre-traversal) check. A post-traveral check is considered to
have made more progress than a pre-traversal check of the same term;
indeed, it also has greater progress than any failure <span style="font-style: italic">within</span>
the term.</div></p><p><div class="SIntrapara">It is, however, possible for multiple potential errors to occur with
the same progress. Here’s one example:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="hspace"> </span><span class="RktVal">"not-even-close"</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected identifier or expected sequence of distinct</span></p></td></tr><tr><td><p><span class="RktErr">binding pairs at: "not-even-close"</span></p></td></tr></table></blockquote></div><div class="SIntrapara">In this case <span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span> reports both errors.</div></p><p><div class="SIntrapara">Even with all of the annotations we have added to our macro, there are
still some misuses that defy <span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span>’s error reporting
capabilities, such as this example:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">mylet: expected more terms at: (mylet)</span></p></td></tr></table></blockquote></div><div class="SIntrapara">The philosophy behind <span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span> is that in these
situations, a generic error such as “bad syntax” is justified. The
use of <span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span> here is so far off that the only informative
error message would include a complete recapitulation of the syntax of
<span class="RktSym"><a href="#%28form._%28%28lib._syntax%2Fscribblings%2Fparse%2Fparse-dummy-bindings..rkt%29._mylet%29%29" class="RktStxLink" data-pltdoc="x">mylet</a></span>. That is not the role of error messages, however; it is
the role of documentation.</div></p><p>This section has provided an introduction to syntax classes, side
conditions, and progress-ordered error reporting. But
<span class="RktSym"><a href="Parsing_Syntax.html#%28form._%28%28lib._syntax%2Fparse..rkt%29._syntax-parse%29%29" class="RktStxLink" data-pltdoc="x">syntax-parse</a></span> has many more features. Continue to the
<a href="stxparse-examples.html" data-pltdoc="x">Examples</a> section for samples of other features in
working code, or skip to the subsequent sections for the complete
reference documentation.</p><div class="navsetbottom"><span class="navleft"><form class="searchform"><input class="searchbox" style="color: #888;" type="text" value="...search manuals..." title="Enter a search string to search the manuals" onkeypress="return DoSearchKey(event, this, "6.1", "../");" onfocus="this.style.color="black"; this.style.textAlign="left"; if (this.value == "...search manuals...") this.value="";" onblur="if (this.value.match(/^ *$/)) { this.style.color="#888"; this.style.textAlign="center"; this.value="...search manuals..."; }"/></form> <a href="../index.html" title="up to the documentation top" data-pltdoc="x" onclick="return GotoPLTRoot("6.1");">top</a></span><span class="navright"> <a href="stxparse.html" title="backward to "1 Parsing and Specifying Syntax"" data-pltdoc="x">← prev</a> <a href="stxparse.html" title="up to "1 Parsing and Specifying Syntax"" data-pltdoc="x">up</a> <a href="stxparse-examples.html" title="forward to "1.2 Examples"" data-pltdoc="x">next →</a></span> </div></div></div><div id="contextindicator"> </div></body></html>
|