A short answer: When compiling a submodule, as for any other module,
imported modules get fresh compile-time instantiations. It you want to
run effects from the enclosing module (which is an implicit import),
the effects must be in `begin-for-syntax`.


A long answer:

When you write

 (module+ test ....)

then all of the `test` parts are assembled together at the end of the
enclosing module in a single `(module* test #f ....)` form.

So,

 (define-syntax x-top (stx-box #'yellow))

 (splicing-let-syntax ([x (syntax-local-value #'x-top)])
   (module+ test
     x))
 
 (set-stx! x-top blue)

 (splicing-let-syntax ([x (syntax-local-value #'x-top)])
   (module+ test
     x))

is the same as

 (define-syntax x-top (stx-box #'yellow))

 (define-syntax x1 (syntax-local-value #'x-top))

 (set-stx! x-top blue)

 (define-syntax x2 (syntax-local-value #'x-top))

 (module* test #f
   x1
   x2)

where `x1` and `x2` each stand for `x` with some distinct scope.


By the time the enclosing module is expanded, but before its submodules
are expanded, that becomes

 (define-syntax x-top (stx-box #'yellow))

 (define-syntax x1 (syntax-local-value #'x-top))

 (void)

 (define-syntax x2 (syntax-local-value #'x-top))

 (module* test #f
   x1
   x2)

Note that the `(set-stx! ....)` form has been macro-expanded away.

The process of expanding the `test` module then creates a new
compile-time instantiation of the enclosing module. Since the
`set-stx!` form has been expanded away to `(void)`, there's no change
to `x-top` during that instantiation.


Replace the definition of `set-stx!` with

 (define-syntax (set-stx! stx)
   (syntax-case stx ()
     [(_ box value)
      #'(begin-for-syntax
          (define-values (x y) (syntax-local-value/immediate #'box))
          (set-stx-box-stx! x #'value))]))

Now, the expansion of the outer module is 

 (define-syntax x-top (stx-box #'yellow))

 (define-syntax x1 (syntax-local-value #'x-top)])

 (begin-for-syntax
   (define-values (x y) (syntax-local-value/immediate #'x-top))
   (set-stx-box-stx! x #'blue))

 (define-syntax x2 (syntax-local-value #'x-top)])

 (module* test #f
   x1
   x2)

As usual (i.e., as in sense of "Composable and Compilable Macros"),
using `begin-for-syntax` preserves the effect for all future
compile-time instantiations of the enclosing module. That way, you get
"yellow" followed by "blue", as you wanted.



At Thu, 17 Dec 2015 15:08:06 -0500, Leif Andersen wrote:
> Hello,
> 
> I am noticing that if I in the body of splicing-let-syntax I put a
> module+, or anything that lifts with
> syntax-local-lift-module-end-decloration really, The stuff that gets
> lifted out doesn't seem  to match what I would expect it to. I suspect
> this is in part do to using prop:rename-transformer, and mutable
> structs, but I don't want to use a syntax-parameter because I would
> like to parameterize over an identifier.
> 
> Here is the code I have:
> 
> #lang racket
> 
> (require racket/splicing)
> 
> (define-syntax (yellow stx) #'"yellow")
> (define-syntax (blue stx) #'"blue")
> 
> (begin-for-syntax
>   (struct stx-box (stx)
>     #:mutable
>     #:transparent
>     #:property prop:rename-transformer
>     (lambda (inst)
>       (syntax-property (stx-box-stx inst) 'not-free-identifier=? #t))))
> (define-syntax (set-stx! stx)
>   (syntax-case stx ()
>     [(_ box value)
>      (begin
>        (define-values (x y) (syntax-local-value/immediate #'box))
>        (set-stx-box-stx! x #'value)
>        #'(void))]))
> 
> (define-syntax x-top (stx-box #'yellow))
> 
> (define-syntax y-top 52)
> 
> (splicing-let-syntax ([x (syntax-local-value #'x-top)])
>   (module+ test
>     x))
> 
> (set-stx! x-top blue)
> 
> (splicing-let-syntax ([x (syntax-local-value #'x-top)])
>   (module+ test
>     x))
> 
> When I run it out I get:
> "yellow"
> "yellow"
> 
> What I would like to get is:
> "yellow"
> "blue"
> 
> Is there any better way to do this, and still have x be an identifier
> that is bound to the correct string?
> 
> Thank you very much.
> 
> ~Leif Andersen
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to