<div dir="ltr"><div><div><div>Christopher,<br><br></div>Ordinary macros are used to extend expressions and definitions; the arguments to class/c are neither, so they are not macro expanded. There are ways to extend other kinds of things with macros -- match expanders, require transformers, provide transformers, and other things like them provide alternate kinds of transformers for syntactic forms other than expressions and definitions. (Hypothetically, we could have used ordinary transformers for them as well, but that's a design question for another day.)<br>
<br></div>If you want class/c* to use macro expansion for its clauses, you'll need to set it up yourself: recognize "clause transformers", invoke the macro transformer on them, simulate some of the aspects of normal macro transformation (e.g. applying a unique mark before and after), and so on.<br>
<br></div>I don't suggest this, though. It doesn't seem necessary. Just do the work of make-button-contracts in the macro that constructs the call to class/c*, and there won't be any nested-expansion to do. Adding a new kind of macro expander is probably overkill for the problem at hand.<br>
<div class="gmail_extra"><br clear="all"><div>Carl Eastlund</div>
<br><br><div class="gmail_quote">On Sat, Sep 21, 2013 at 2:15 PM, Christopher <span dir="ltr"><<a href="mailto:ultimatemacfanatic@gmail.com" target="_blank">ultimatemacfanatic@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 style="word-wrap:break-word">Hello, all you wonderful people. I'm seeing some strange behavior from my macros.<div><br></div><div>So I invoke my <span style="font-family:Courier"><u>define-sequencer-buttons-info-class</u></span> macro with a bunch of identifiers.</div>
<div>Its job is to rename the identifiers to add a "-btn" suffix (yes, I use macros to save typing tedium) and then</div><div>invoke my <span style="font-family:Courier"><u>make-button-contracts</u></span> macro inside of my <font style="text-decoration:underline" face="Courier">class/c*</font><font> macro. The job of the former is to expand</font></div>
<div><font>into a literal form that starts with </font><u style="font-family:Courier">init-field-accessor</u> with some extra arguments which is interpreted specially by the latter. </div><div>When I can get <font style="text-decoration:underline" face="Courier">make-button-contracts</font><font> to be invoked, it</font> runs correctly, expanding into an argument list starting with <u><font face="Courier">init-field-accessor</font></u>.</div>
<div><font><br></font></div><div><font><u><font face="Courier">class/c*</font></u> (star at the end) is my macro that expands argument pairs starting with literal symbols <u><font face="Courier">init-field-accessor</font></u> and <font style="text-decoration:underline" face="Courier">field-accessor</font><font> </font></font></div>
<div><font><font>into sets of init, field, and method definitions for mutations of a given name---or passes regular class/c statements through unmodified.</font></font></div><div><font><font><br></font></font></div><div>
<font><font>The problem is that when Racket is in the <u><font face="Courier">define-sequencer-buttons-info-class</font></u> transformer procedure, it constructs a definition including</font></font></div>
<div><font><font>an invocation of </font></font><span style="font-family:Courier"><u>make-button-contracts</u></span> nested inside my invocation of <u style="font-family:Courier">class/c*</u>. When <u><font face="Courier">class/c*</font></u> then gets expanded, it passes the </div>
<div>invocation of <u style="font-family:Courier">make-button-contracts</u> through to the standard <u><font face="Courier">class/c</font></u> (without the star)---unmodified----and then starts expanding <u><font face="Courier">class/c </font></u></div>
<div>without having first expanded <u style="font-family:Courier">make-button-contracts</u>. </div><div><br></div><div>It further seems, that <u style="font-family:Courier">class/c</u> does not macro-expand any of its arguments, but only matches literal names, so how am I going to get my <u><font face="Courier">make-button-contracts</font></u> to expand</div>
<div>BEFORE <u><font face="Courier">class/c*</font></u> is expanded? How can I do this with Racket?</div><div><br></div><div>Finally, lest anyone be confused. I use a convention where my s-expression lists that represent immediate procedure applications at that point in the source are surrounded with braces, the ones that are expanded to macros or core, non-procedure functionality are in parentheses, and the rest are in brackets. It's unconventional, but it works for me.</div>
<div><font><font><br></font></font></div><div><font><font><br></font></font></div><div>Many thanks!</div><div><br></div><div>---Christopher</div><div><font><font><br></font></font></div><div><br></div><div><font face="Courier">; module total-ca-state.rkt (main file) </font><span style="font-family:Courier">[ file abbreviated to relevant portions ]</span></div>
<div><font face="Courier"><br></font></div><div><div><font face="Courier">(define-syntax [make-button-contracts stx]</font></div><div><font face="Courier"> (syntax-case stx []</font></div><div><font face="Courier"> [[_ btn-name ...]</font></div>
<div><font face="Courier"> (let [[ret </font><span style="font-family:Courier">#'(init-field-accessor [btn-name {is-a?/c button-info%}] ...)]]</span></div><div><font face="Courier"> {print ret}</font></div>
<div><font face="Courier"> ret )]))</font></div><div><font face="Courier"><br></font></div><div><font face="Courier">(define-syntax [define-sequencer-buttons-info-class stx]</font></div><div><font face="Courier"> (syntax-case stx []</font></div>
<div><font face="Courier"> [[_ name button ...]</font></div><div><font face="Courier"> (let [[buttons </font></div><div><font face="Courier"> (for/list [[btn-id {in-list {syntax->list #'[button ...]}}]]</font></div>
<div><font face="Courier"> {datum->syntax </font></div><div><font face="Courier"> btn-id</font></div><div><font face="Courier"> {string->symbol</font></div><div><font face="Courier"> {string-append</font></div>
<div><font face="Courier"> {symbol->string {syntax->datum btn-id}} </font></div><div><font face="Courier"> "-btn" }}</font></div><div><font face="Courier"> btn-id</font></div>
<div><font face="Courier"> btn-id })]]</font></div><div><font face="Courier"> (define ret</font></div><div><font face="Courier"> #`(define name</font></div><div><font face="Courier"> (class/c*</font></div>
<div><font face="Courier"> (make-button-contracts #,@buttons) )))</font></div><div><font face="Courier"> {print ret} </font></div><div><font face="Courier"> ret )]))</font></div><div><br></div>
<div><font face="Courier"> </font></div><div><span style="font-family:Courier">(provide sequencer-buttons-info%)</span></div><div><font face="Courier">(define-sequencer-buttons-info-class sequencer-buttons-info%</font></div>
<div><font face="Courier"> next-user</font></div><div><font face="Courier"> previous-user</font></div><div><span style="font-family:Courier"> ; ... long list of names (abbreviated) ...</span></div><div><font face="Courier"> lock-user</font></div>
<div><font face="Courier"> )</font></div><div><br></div></div><div><br></div><div><br></div><div><br></div><div><font face="Courier">; module class-util.rkt (required by the other file) [ truncated to relevant portions ]</font></div>
<div><font face="Courier"><br></font></div><div><font face="Courier"><div>(define-syntax [class/c* stx]</div><div> (define [flatten lst [times 1]]</div><div> (if {zero? times}</div><div> lst</div><div> {flatten {apply append lst} {sub1 times}} ))</div>
<div> (syntax-case stx []</div><div> [[_ clause ...]</div><div> (let []</div><div> (define clause-list {syntax->list #'[clause ...]})</div><div> (when {zero? {length clause-list}}</div><div> {raise-syntax-error #f</div>
<div> "must supply at least one clause"</div><div> stx })</div><div> (define syntax-ret</div><div> {datum->syntax</div><div> stx</div>
<div> {append</div><div> {list #'class/c}</div><div> {flatten</div><div> (for/list [[clause {in-list clause-list}]]</div><div> (syntax-case clause [init-field-accessor field-accessor]</div>
<div> [[init-field-accessor sub-clause ...]</div><div> {init-field-accessor* clause} ]</div><div> [[field-accessor sub-clause ...]</div><div> {field-accessor* clause} ]</div>
<div> </div><div> ; THIS IS WHERE THE CALL TO make-button-contracts IS PASSED THRU TO REGULAR class/c</div><div> [whole-thing {list {list clause}}] )) </div><div> 2 }}</div>
<div> stx})</div><div> {print syntax-ret}</div><div> syntax-ret )]))</div><div><br></div></font></div></div><br>____________________<br>
Racket Users list:<br>
<a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
<br></blockquote></div><br></div></div>