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:

#lang racket
(require syntax/parse/define)
(define-simple-macro (with-tables stem body ...)
  #:with table-author-id (syntax-local-introduce #'table-author)
  (let([table-publication (string-append stem "_publication")]
       [table-author-id (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) ;”x_author"


On Jan 15, 2015, at 9:23 PM, Alexander McLin <alex.mc...@gmail.com> wrote:

> Warning I am still a Racket intermediate user but I've been studying 
> syntactic extensions a lot the past several months.
> 
> 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.
> 
> 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.
> 
> The table-author identifier in the macro in the let form is renamed to 
> something different like g6271 or something along those lines.
> 
> 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.
> 
> (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:
> 
> (let ((g6191 (string-append "x" "_publication"))
>        (g6271 (string-append "x" "_author"))
>        (g6369 (string-append "x" "_bridge_publication_author"))
>        (g6445 (string-append "x" "_unique_counters")))
>    table-author)
> 
> Note that the original table-author identifier has been replaced by a 
> different identifier that still has the same binding you originally defined.
> 
> 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.
> 
> (with-tables "x" "hello") works because what you get in return is:
> 
> (let ((g6191 (string-append "x" "_publication"))
>        (g6271 (string-append "x" "_author"))
>        (g6369 (string-append "x" "_bridge_publication_author"))
>        (g6445 (string-append "x" "_unique_counters")))
>    "hello")
> 
> "hello" is just a self-evaluating string giving you back "hello" from within 
> the let form.
> 
> On Thu, Jan 15, 2015 at 12:12 AM, Thomas Lynch 
> <thomas.ly...@reasoningtechnology.com> wrote:
> I have a simple syntax rule:
> 
>   Welcome to Racket v5.2.1.
>   racket@> (define-syntax-rule (with-tables stem 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 ...
>       ))
> 
> Which works fine when I don't reference the environment defined by the let:
> 
>   racket@>
>   racket@> (with-tables "x" "hello")
>   "hello"
> 
> 
> However when I pass it an identifier corresponding to one of the variables 
> defined in the let:
> 
>   racket@> (with-tables "x" table-author)
>   reference to undefined identifier: table-author
>   stdin::1167: table-author
> 
> 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.
> 
> ... 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? 
> 
> Thanks in advance for explaining the evaluation/context model here.
> 
> Thomas 
> 
> _________________________
>   Racket Developers list:
>   http://lists.racket-lang.org/dev
> 
> 
> _________________________
>  Racket Developers list:
>  http://lists.racket-lang.org/dev

_________________________
  Racket Developers list:
  http://lists.racket-lang.org/dev

Reply via email to