[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

Reply via email to