<div dir="ltr">Thank you for that nice explanation. I'm reminded of the scope variables carried in Ruby. In Mathematica the renaming of module variables is explicit. There do not appear to be run phases there. Also thanks for the working example using syntax parse. Thus far I have working examples using define-syntax via datum and define-syntax with case (thanks to Matthais). <div><br></div><div>The following questions might best be answered by pointing me to some other docs, haven't run across yet:<br><br>Are there more than two phases? There is the syntax phase, i.e. compile time phase, and then a run phase. Lexical scope at the syntax phase would be static based textual layout of the program - i.e. lexical scope. Then the macros (syntax transformers) are gone (as the syntax has been transformed) after the syntax phase. At run time then, we have no access to the syntax object information? <br><br>Academic question, but can syntax information, or other values be shared across phases? As an example, could one store the file name, line, and column number for an identifier, the make use of that later?<br><br>How is it that we do work inside of a macro, for example by making use of require-for-syntax? Does that imply that the routines that we make use of in the macro for doing work had their own syntax phase, and now they are in run time phase during the macro's syntax phase? .. then if those worker routines make use of macros ... seems this recursion could be arbitrarily deep.<br><br>Can the syntax analysis be explicitly invoked? Sort of like (apply ...) or (eval ..) ? Come to think of it, eval must do the syntax phase, then the run phase, so perhaps it is calls to that which causes the recursion.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jan 16, 2015 at 11:01 AM, Alexander D. Knauth <span dir="ltr"><<a href="mailto:alexander@knauth.org" target="_blank">alexander@knauth.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>But I think it’s important that it doesn’t use gensym or something like that, it uses syntax-marks, which means you can break these lexical scoping rules if you want/need to by using either syntax-local-introduce or datum->syntax:</div><div><br></div><div><div>#lang racket</div><div>(require syntax/parse/define)</div><div>(define-simple-macro (with-tables stem body ...)</div><div> #:with table-author-id (syntax-local-introduce #'table-author)</div><span class=""><div> (let([table-publication (string-append stem "_publication")]</div></span><div> [table-author-id (string-append stem "_author")]</div><span class=""><div> [table-bridge-publication-author (string-append stem "_bridge_publication_author")]</div><div> [table-unique-counters (string-append stem "_unique_counters")]</div><div> )</div><div> body ...</div><div> ))</div></span><div>(with-tables "x" table-author) ;”x_author"</div></div><div><div class="h5"><div><br></div><br><div><div>On Jan 15, 2015, at 9:23 PM, Alexander McLin <<a href="mailto:alex.mclin@gmail.com" target="_blank">alex.mclin@gmail.com</a>> wrote:</div><br><blockquote type="cite"><div dir="ltr"><div>Warning I am still a Racket intermediate user but I've been studying syntactic extensions a lot the past several months.</div><div><br></div>The problem here is macros in Racket have lexical scope just like procedures, they are hygienic macros. The identifiers you introduced in the with-tables macro only exist or refer to other bindings in the same lexical scope as where you originally wrote the macro.<div><br></div><div>When you invoke the macro and pass in table-author, even though it is spelled the same as the identifier you wrote in the macro definition, they are not the same. When the macro expands, hygiene is implemented by renaming all identifiers in the macro to unique non-clashing symbols that don't conflict with others existing in the scope the macro is expanding in.</div><div><br></div><div>The table-author identifier in the macro in the let form is renamed to something different like g6271 or something along those lines.</div><div><br></div><div>Furthermore, you need to be careful about what you mean by evaluation. In the presence of macros, you have the concept of syntax phase(or compile-time or expand-time) evaluation versus run-time evaluation. When the macro is expanding, it does it thing, processing the original syntax into the new piece of syntax that replaces what was there previously such as (with-tables "x" table-author) which is then finally evaluated during run-time.</div><div><br></div><div>(with-tables "x" table-author) will expand into something looking similar to the following, just to give you an idea of what macro expansion looks like:</div><div><br></div><div><div>(let ((g6191 (string-append "x" "_publication"))</div><div> (g6271 (string-append "x" "_author"))</div><div> (g6369 (string-append "x" "_bridge_publication_author"))</div><div> (g6445 (string-append "x" "_unique_counters")))</div><div> table-author)</div></div><div><br></div><div>Note that the original table-author identifier has been replaced by a different identifier that still has the same binding you originally defined.</div><div><br></div><div>The table-author identifier you passed to the macro gets inserted in the body position and then the expanded code is evaluated at run-time and of course gives you a run-time error since table-author does not refer to anything and thus when it's evaluated, it is recognized as an undefined identifier.</div><div><br></div><div>(with-tables "x" "hello") works because what you get in return is:</div><div><br></div><div><div>(let ((g6191 (string-append "x" "_publication"))</div><div> (g6271 (string-append "x" "_author"))</div><div> (g6369 (string-append "x" "_bridge_publication_author"))</div><div> (g6445 (string-append "x" "_unique_counters")))</div><div> "hello")</div></div><div><br></div><div>"hello" is just a self-evaluating string giving you back "hello" from within the let form.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jan 15, 2015 at 12:12 AM, Thomas Lynch <span dir="ltr"><<a href="mailto:thomas.lynch@reasoningtechnology.com" target="_blank">thomas.lynch@reasoningtechnology.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">I have a simple syntax rule:<br><br><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div> Welcome to Racket v5.2.1.</div><div> racket@> (define-syntax-rule (with-tables stem body ...)</div><div> (let(</div><div> [table-publication (string-append stem "_publication")]</div><div> [table-author (string-append stem "_author")]</div><div> [table-bridge-publication-author (string-append stem "_bridge_publication_author")]</div><div> [table-unique-counters (string-append stem "_unique_counters")]</div><div> )</div><div> body ...</div><div> ))</div><div><br></div></blockquote>Which works fine when I don't reference the environment defined by the let:<br><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><br></div><div> racket@></div><div> racket@> (with-tables "x" "hello")</div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div> "hello"<br></div><div><br></div><div><br></div></blockquote>However when I pass it an identifier corresponding to one of the variables defined in the let:<div><br><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div> racket@> (with-tables "x" table-author)</div><div> reference to undefined identifier: table-author</div><div> stdin::1167: table-author</div><div><br></div></blockquote>The identifier passed in doesn't seem to be part of the local let context, but carried in a different context, or perhaps it was evaluated as an operand. I didn't expect either of those. Can someone point me at a description of the expected behavior, or give me a tip here on what is happening and why.<br><br>... in Wolfram language there is a 'Hold' operator for situations like this. Apparently inside the macro we have to do some evaluation to handle the work of the macro, is that why the operand is evaluated? <br><br>Thanks in advance for explaining the evaluation/context model here.<span><font color="#888888"><br><br>Thomas </font></span></div></div>
<br>_________________________<br>
Racket Developers list:<br>
<a href="http://lists.racket-lang.org/dev" target="_blank">http://lists.racket-lang.org/dev</a><br>
<br></blockquote></div><br></div>
_________________________<br> Racket Developers list:<br> <a href="http://lists.racket-lang.org/dev" target="_blank">http://lists.racket-lang.org/dev</a><br></blockquote></div><br></div></div></div></blockquote></div><br></div>