I reformulated/clarified the question and bumped it over to the developers, you can find it there. Thanks for helping with this.
On Thu, Jan 15, 2015 at 12:46 PM, Thomas Lynch < thomas.ly...@reasoningtechnology.com> wrote: > Matthias, > > I appreciate your patience. I did see the 'pattern better than direct > access' and other style discussion on a tutorial on the net, and I do get > that. The first macro presented in the original post was to show the > desired behavior and to show the code runs without errors. This stands in > contrast to the define-syntax-rule example, which throws an error - note > the subject of my post. > > You haven't commented on the error or why the syntax rule evaluates the > operand. If "macros do not evaluate anything", which was my expectation > also, and the expansion occurs in hygienically at the scope of the let at > run time, which was also my expectation, then where is the 'undefined > identifier' error coming from? > > You can see the error thrown by running the define-syntax-rule example, as > shown in the original post along with its output. > > Thomas > > > > On Thu, Jan 15, 2015 at 12:07 PM, Matthias Felleisen <matth...@ccs.neu.edu > > wrote: > >> >> [cc user@ again] >> >> There is no bug in syntax-rule/s. >> >> Macros do not evaluate anything. They rewrite code. Code refers to >> identifiers. This relation must remain apparent. >> >> That's it. -- Matthias >> >> >> >> >> >> >> On Jan 14, 2015, at 9:57 PM, Thomas Lynch wrote: >> >> As for the demonstrative example at the top of the original post, I now >> understand you are speaking of clarity and style rather than a functional >> problem with it. I enjoyed that discussion on clarity, intention, and >> aesthetics. >> >> As for the question of why the 'body' argument is being evaluated as an >> operand rather as part of the expansion, and thus resulting in an undefined >> identifier error, am I correct to read your answer above, that this is >> indeed a bug? "macro-site variables are bound by macro-contexts" but >> clearly that is not happening - or the error wouldn't be issued. >> >> IMHO the define-syntax-rule would be the clearest implementation for the >> reader for the reasons you give. Too bad there is a bug in it. (The >> operand should not be evaluated except as part of the macro expansion, as >> you note. I am reading you on this correctly? I have a hard time >> understanding why an operand to a macro would be evaluated before it is >> included in the expansion, unless it was a limitation of the interpreter, >> but if it is a bug, then good as it can be fixed.) >> >> On Thu, Jan 15, 2015 at 9:53 AM, Matthias Felleisen <matth...@ccs.neu.edu >> > wrote: >> >>> >>> On Jan 14, 2015, at 8:14 PM, Thomas Lynch wrote: >>> >>> Matthias thank you for fielding my question, though two things are not >>> clear. I hope you or someone might clarify. >>> >>> Firstly, is there a reason to prefer the macro you present over the >>> first one given in the original post. I believe they both work. Neither >>> uses the more elegant syntax-rule. >>> >>> >>> >>> Code that works is fine. Code that clearly explains its intention is >>> better. Since syntactic extensions are (basically) extensions to the >>> grammar, their specification ought to bring across (a) what kind of new >>> expressions programmers may write down and (b) what these new expressions >>> mean. I think separating these cleanly is also important. >>> >>> With syntax-case, which isn't all that different from syntax-rules, you >>> get (a) easily: >>> >>> (with-tables stem body ...) >>> >>> Compare this to your three or four lines that stx apart. When your >>> extension is even more complicated, you definitely want this pattern >>> matching notation because it is close to the way people write grammars and >>> because you can automatically check certain properties (see syntax-parse). >>> >>> For (b), constructing a piece of syntax manually with backquote, comma, >>> splice is again much more complicated than writing down a rewrite rule. In >>> particular, you get a really good handle at the manipulation of scope, >>> which is one of the primary functions of syntactic extensions. >>> >>> Racket like Scheme like Lisp is about being able abstract boiler plate. >>> Syntax-case abstracts your boiler plate for (a) and (b). >>> >>> Ideally, I would like to separate (a) from (b) so that programmers can >>> specify (a) at the module boundary, just like contracts for functions. >>> That's what I started Ryan on and we ended up syntax-parse. It' s a >>> fantastic first step but there is work left to do. Probably another >>> dissertation. >>> >>> >>> Secondly, and this is the question I'm really getting at, is there a >>> reason that the operands given to syntax-rules must have identifiers within >>> lexical scope at the point of the macro call, rather than lexical scope at >>> the point of their use within the macro? >>> >>> >>> Lexical scope is critical for program comprehension. Programmers read >>> programs a lot more often than they write them. Lexical scope guarantees >>> that when they read programs all identifiers are resolved (bound) to a >>> declaration (binding position) that can be found by reading the text -- not >>> running the program. By finding it in the text w/o running it, you have a >>> better chance of predicting what the program does when you run it. >>> >>> Macros rewrite program text. In the process, they substitute use-site >>> code into macro-definition code and macro-definition code is substituted >>> into use-site code. Each substitution may affect lexical scope when >>> performed without respect to lexical scope. Each substitution may thus bind >>> variables to binding occurrences that you can only figure out by running >>> code. Enforcing that >>> >>> use-site variables are bound by use-context >>> macro-site variables are bound by macro-contexts >>> >>> ___by default___ is called hygienic expansion and almost always gives >>> you what you want. >>> >>> On rare occasion, an extension of Racket's grammar also needs to break >>> these default rules. syntax-case/parse allow programmers to break those >>> rules in a way that is still easy to read off from the code. >>> >>> That's why it's the right way to go about syntax extensions. -- Matthias >>> >>> >>> >>> >>> >>> >>> >>> Off hand the latter seems to be the proper behavior for a macro, i.e. >>> perhaps this is a bug? Can anyone here tell me why it behaves like this? >>> >>> >>> On Thu, Jan 15, 2015 at 4:12 AM, Matthias Felleisen < >>> matth...@ccs.neu.edu> wrote: >>> >>>> >>>> You want something like this: >>>> >>>> (define-syntax (with-tables stx) >>>> (syntax-case stx () >>>> [(with-tables stem body ...) >>>> (let ([table-author (datum->syntax stx 'table-author)] >>>> ;; ... ditto for other identifiers for which you wish to >>>> break lexical scope >>>> ) >>>> #`(let ([table-publication (string-append stem "_publication")] >>>> [#,table-author (string-append stem "_author")] >>>> [table-bridge-publication-author (string-append stem >>>> "_bridge_publication_author")] >>>> [table-unique-counters (string-append stem >>>> "_unique_counters")]) >>>> body ...))])) >>>> >>>> (with-tables "x" table-author) >>>> >>>> ;; --- >>>> >>>> To achieve this with syntax-rules would be, well, hard. >>>> >>>> ;; --- >>>> >>>> The accepted way of writing this macro is: >>>> >>>> (define-syntax (with-tables stx) >>>> (syntax-case stx () >>>> [(with-tables stem (table-author >>>> ;; ... add other names you wish to bind in body >>>> ) >>>> body ...) >>>> #`(let ([table-publication (string-append stem "_publication")] >>>> [table-author (string-append stem "_author")] >>>> [table-bridge-publication-author (string-append stem >>>> "_bridge_publication_author")] >>>> [table-unique-counters (string-append stem >>>> "_unique_counters")]) >>>> body ...)])) >>>> >>>> (with-tables "x" (table-author) table-author) >>>> >>>> >>>> >>>> >>> >>> >> >> >
____________________ Racket Users list: http://lists.racket-lang.org/users