Wow, I really butchered a sentence. Let me try it again.

Old: "That is, there's a compile-time "pass" where Racket is focuses on the 
code you write and what they can see"

New: "That is, there's a compile-time "pass" where Racket focuses on replacing 
used macros with new code, and that pass has its own set of bindings that only 
that pass can see."

~slg

-------- Original Message --------
On May 9, 2021, 3:14 PM, Sage Gerard wrote:

> I'm stretching details a bit, but maybe it would help to think of phases as 
> "passes." That is, there's a compile-time "pass" where Racket is focuses on 
> the code you write and what they can see. These passes continue until the 
> Racket program is fully expanded.
>
> Where things get tricky is remembering that when you create a binding at one 
> phase, it is available for that phase. It's a little easier to tell the 
> difference across module boundaries.
>
> Let's say you have a library that defines your functions at phase 0, or 
> runtime.
>
> ; lib.rkt
> #lang racket/base
> (provide (all-defined-out))
> (define (my-function x) (+ x 1))  (define (my-macro stx)
> (datum->syntax stx (my-function (cadr (syntax->datum stx)))))
>
> Now let's have another module use the syntax transformer. I'm handwaving 
> around some details because `define-syntax` and `define-for-syntax` are not 
> the same, but I'd like to focus on illustrating how phases operate.
>
> #lang racket/base
> (require "lib.rkt")
> (my-macro #'(x 1))
>
> The reason this works is because all the bindings are in the same phase. That 
> is, everything was defined in the same pass. Now let's shift it all one phase 
> up, which will break the program because it no longer sees my-macro, or even 
> enough of racket/base to apply functions.
>
> #lang racket/base
> (require (for-syntax "lib.rkt"))
> (my-macro #'(x 1))
>
> Right now `my-macro` is in phase 1 relative to this module. So we have to 
> "lift" the rest of the code to match.
>
> #lang racket/base
> (require (for-syntax racket/base "lib.rkt"))
> (begin-for-syntax (my-macro #'(x 1)))
>
> This still isn't particularly useful because most of the time, a module 
> manages multiple phases at once. It can be harder to visualize, but the 
> principle is the same: When code runs at a certain phase, is everything that 
> code needs to run also available at that phase? It's still just Racket. I 
> like to visualize it as running at a different "layer" on top of the code 
> that I know will eventually execute at runtime. Here's another example that 
> can help drive the point home. Run it using the `racket` command.
>
> #lang racket/base
> (require (for-syntax racket/base))
>
> (define a "foo")
> (define-for-syntax a 1)
>
> (displayln a)
> (begin-for-syntax (displayln a))
>
> Notice that you see "1" first, before "foo", even though the displayln for 
> the "1" is after the displayln for "foo".
>
> So to answer your question, if you have something you want available across 
> phases, you need to bind that same value across phases. Here's a simplified 
> example.
>
> #lang racket/base
> (require (for-syntax racket/base))
>
> (define-syntax-rule (define-across-phases id v)
> (begin (define id v)
> (define-for-syntax id v)))
>
> (define-across-phases a 1)
>
> (displayln a)
>
> (begin-for-syntax (displayln a))
>
> Notice that I leverage a phase to define an identifier twice: Once for the 
> current phase, and once for the phase +1 "layer" up.
>
> But... I normally do bind across phases using (require) with both for-syntax 
> and without a phase shift. e.g. (require "lib.rkt" (for-syntax "lib.rkt")). 
> There are times I'll need cross-phase definitions only within one module, but 
> it doesn't come up much for me.
>
> Hope this helps.
>
> On 5/9/21 3:53 AM, Yushuo Xiao wrote:
>
>> I am using syntax transformers to define macros in Racket. I want to create 
>> some helper functions to help me manipulate the syntax. However, the 
>> functions I defined outside the syntax transformer are not available inside 
>> the syntax transformer. For example, in the following code
>>
>> (define (my-function x) (+ x 1))
>>
>> (define-syntax my-macro
>> (lambda (stx)
>> (datum->syntax stx (my-function (cadr (syntax->datum stx))))))
>>
>> I got the error "my-function: reference to an unbound identifier at phase: 
>> 1; the transformer environment".
>>
>> After some searching, I am able to write the following code so that 
>> `my-function` is available inside the syntax transformer.
>>
>> (begin-for-syntax
>> (define (my-function x) (+ x 1)))
>> (provide (for-syntax my-function))
>>
>> (define-syntax my-macro
>> (lambda (stx)
>> (datum->syntax stx (my-function (cadr (syntax->datum stx))))))
>>
>> But the problem is, `my-function` is not available outside the syntax 
>> transformer this time. Sometimes I want to check those helper functions in 
>> ordinary code, so I need to be able to call it from both inside and outside 
>> the syntax transformer, just like the function `cadr`. How can I achieve 
>> that?
>>
>> I know my question has something to do with Racket's syntax model, in 
>> particular the concept of "phase level", but I never really understand it. 
>> If you could provide some easy-to-follow tutorials explaining it I would 
>> even be more grateful.
>> --
>> 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 [email protected].
>> To view this discussion on the web visit 
>> [https://groups.google.com/d/msgid/racket-users/46cce5b2-251b-481c-afe2-28582e8c44f3n%40googlegroups.com](https://groups.google.com/d/msgid/racket-users/46cce5b2-251b-481c-afe2-28582e8c44f3n%40googlegroups.com?utm_medium=email&utm_source=footer).
>
> --
> ~slg
>
> --
> 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 [email protected].
> To view this discussion on the web visit 
> [https://groups.google.com/d/msgid/racket-users/02b5016d-67f8-f44d-2924-c7f1b4c022a0%40sagegerard.com](https://groups.google.com/d/msgid/racket-users/02b5016d-67f8-f44d-2924-c7f1b4c022a0%40sagegerard.com?utm_medium=email&utm_source=footer).

-- 
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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/v3kmdKboUfKmBf9GVBIiEjBTy2eXWqaJziKOXcLlnZbvJTt4K2W1P-I6SskzJ26H4Sr0FZCdxB9FWaJWsEJUih0TcYvgpTlrI8Hn572kh1k%3D%40sagegerard.com.

Reply via email to