<div dir="ltr">The concept is pretty opaque; syntax object contexts are a fairly tricky, black-magic part of the language. There is a rhyme and reason to them, but it isn't terribly high level or user-friendly. Sadly, no one yet knows how to do better for macros as powerful as Racket's. I've spent a long time with them, and I got the deepest understanding from reading Kent Dybvig's paper "Syntactic Abstraction in Scheme" over and over. And eventually implementing it myself, which was incidental but certainly made things crystal clear. I don't know that it's necessary to go that far to work with advanced macros; mostly, writing things with default hygiene as much as possible, and occasionally using syntax-local-introduce for tricky stuff like macros that produce units or require forms, will get you pretty far.<br>
</div><div class="gmail_extra"><br clear="all"><div>Carl Eastlund</div>
<br><br><div class="gmail_quote">On Tue, Aug 6, 2013 at 5:57 PM, Nick Main <span dir="ltr"><<a href="mailto:david.nick.main@gmail.com" target="_blank">david.nick.main@gmail.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">Many thanks !<div><br></div><div>The problem makes sense and the solution works.</div><div><br></div><div>Are there any explanations of "syntax marks" beyond those in the "Syntax Model" section of the documentation ? The concept seems opaque.</div>
</div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Aug 6, 2013 at 2:32 PM, Carl Eastlund <span dir="ltr"><<a href="mailto:cce@ccs.neu.edu" target="_blank">cce@ccs.neu.edu</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"><div><div><div>Nick,<br><br></div>The unit system has some non-hygienic behavior, by design. That is, it introduces names that aren't part of its input, which isn't the default behavior of hygienic macros. Of course we want this -- we want the macro use-dog to bind the names woof and bark, which aren't directly part of its input. But getting the context right, and still "playing nice" with other hygienic macros, is slightly tricky.<br>
<br></div>So in this context, what's the trick? The names bound by define-values/invoke-unit are bound in the context that the interface names are written in. Note that the interface names in use-dog are written inside the macro definition. The macro system assumes anything from inside a macro is a local or "temporary" name that should be hidden from the rest of the program. You can fix this with the syntax-local-introduce function, which (basically) toggles the context of a given syntax object between the current macro expansion step and its call site.<br>
<br></div>So right now you are getting two definitions each for woof and bark, one visible by the main module and one only visible from the expansion of the use-dog macro. If you call use-dog multiple times, you'll get more, separate, unique contexts.<br>
<br>You can fix it like this, to make use-dog bind things in the context where it is called:<br><br> (define-syntax (use-dog stx)<br> (syntax-case stx ()<br> ([_ dog-unit]<br> #`(define-values/invoke-unit dog-unit<br>
(import)<br> (export #,(syntax-local-introduce #'dog^))))))<span><font color="#888888"><br><br clear="all"></font></span><div class="gmail_extra"><span><font color="#888888"><div>
Carl Eastlund</div>
<br></font></span><div class="gmail_quote"><div>On Tue, Aug 6, 2013 at 5:11 PM, Nick Main <span dir="ltr"><<a href="mailto:david.nick.main@gmail.com" target="_blank">david.nick.main@gmail.com</a>></span> wrote:<br>
</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>
<div dir="ltr"><font face="courier new, monospace">I am attempting to write a macro to clean up the use of define-values/invoke-unit and finding some confusing behavior.</font><div><font face="courier new, monospace"><br>
</font></div>
<div><font face="courier new, monospace">My macros module is:</font></div><div><font face="courier new, monospace"><br></font></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div><font face="courier new, monospace">#lang racket</font></div>
</div><div><div><font face="courier new, monospace">(provide (all-defined-out))</font></div></div><div><div><font face="courier new, monospace"><br></font></div></div><div><div><font face="courier new, monospace">(define-signature dog^</font></div>
</div><div><div><font face="courier new, monospace"> (woof</font></div></div><div><div><font face="courier new, monospace"> bark))</font></div></div><div><div><font face="courier new, monospace"><br></font></div></div>
<div><div><font face="courier new, monospace">(define mutt@</font></div></div><div><div><font face="courier new, monospace"> (unit</font></div></div><div><div><font face="courier new, monospace"> (import)</font></div>
</div><div><div><font face="courier new, monospace"> (export dog^)</font></div></div><div><div><font face="courier new, monospace"> (define (woof) (printf "Wuf !!\n"))</font></div></div><div><div><font face="courier new, monospace"> (define (bark) (printf "RarRarRar !!\n"))))</font></div>
</div><div><div><font face="courier new, monospace"><br></font></div></div><div><div><font face="courier new, monospace">(define-syntax use-dog</font></div></div><div><div><font face="courier new, monospace"> (syntax-rules ()</font></div>
</div><div><div><font face="courier new, monospace"> ([_ dog-unit]</font></div></div><div><div><font face="courier new, monospace"> (define-values/invoke-unit dog-unit</font></div></div><div><div><font face="courier new, monospace"> (import)</font></div>
</div><div><div><font face="courier new, monospace"> (export dog^)))))</font></div></div></blockquote><font face="courier new, monospace"><br></font><div><font face="courier new, monospace">..and the module using it is:</font></div>
<div><font face="courier new, monospace"><br></font></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="courier new, monospace"><div>#lang racket</div></font></div><div><font face="courier new, monospace"><div>
(require "macros.rkt")</div></font></div><div><font face="courier new, monospace"><div><br></div></font></div><div><font face="courier new, monospace"><div>(define-values/invoke-unit mutt@</div></font></div><div>
<font face="courier new, monospace"><div> (import)</div></font></div><div><font face="courier new, monospace"><div> (export dog^))</div></font></div><div><font face="courier new, monospace"><div><br></div></font></div>
<div>
<font face="courier new, monospace"><div>(use-dog mutt@)</div></font></div><div><font face="courier new, monospace"><div><br></div></font></div><div><font face="courier new, monospace"><div>(woof)</div></font></div><div>
<font face="courier new, monospace"><div>
(woof)</div></font></div><div><font face="courier new, monospace"><div>(bark)</div></font></div><div><font face="courier new, monospace"><div>(woof)</div></font></div></blockquote><div><font face="courier new, monospace"><div>
<br></div><div>I am trying to make the "use-dog" macro expand to the equivalent define-values/invoke-unit form as shown.</div><div>If I comment out the define-value/invoke-unit form I get warning about unbound identifier woof - implying that the (use-dog dog^) form is not doing the job. Moreover, the second module as it stands does not give a warning about duplicate definitions for woof or bark (as it does if I duplicate the define-values/invoke-unit form) - further indicating the non-action of use-dog.</div>
<div><br></div><div>The macro stepper shows use-dog expand exactly as expected, but it then seems to be ignored without any warnings.</div><div><br></div><div>Is there something I am misunderstanding here, or is this a bug ?</div>
</font></div></div>
<br></div></div><div>____________________<br>
Racket Users list:<br>
<a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
<br></div></blockquote></div><br></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>