[racket] Lack of understanding of how module loading work with (for-syntax)

From: Dmitry Pavlov (dpavlov at ipa.nw.ru)
Date: Wed Sep 25 06:44:44 EDT 2013

Ryan,

Thank you, your explanation about DrRacket's debugging and "raco make"
has really made sense to me. Also, it helped me to figure my
original problem in more specific terms; I will do a separate post
about it.

Regards,

Dmitry


On 09/25/2013 09:52 AM, Ryan Culpepper wrote:
> Are you running this in DrRacket with debugging turned on? If so, that
> will confuse the issue; you get more lines because of the way debugging
> is implemented. Here's what I get when I start racket and require "d.rkt":
>
> $ racket
> Welcome to Racket v5.3.5.
>  > (require "d.rkt")
> making s-h
> making s-h
> making s-h
> making s-h
> CT 1 : xx
> CT 2 : yy
> making s-h
> making h
> RT 1 : x
> RT 2 : y
>
> (I changed "d.rkt" to add "CT" and "RT" to the compile-time and run-time
> printfs, respectively.)
>
> Let's break that down by running the compiler explicitly using raco make:
>
> $ raco make a.rkt
> making s-h
>
> $ raco make b.rkt
> making s-h
>
> $ raco make c.rkt
> making s-h
>
> $ raco make d.rkt
> making s-h
> CT 1 : xx
> CT 2 : yy
>
> Okay, so just compiling the modules (which happened implicitly before)
> accounts for the first 6 lines of the original output. And it shows that
> we get a fresh instantiation of the compile-time parts of the modules
> (in particular, the s-h variable) for each compilation.
>
> What about running the modules now (using the compiled code)?
>
> $ racket d.rkt
> making h
> RT 1 : x
> RT 2 : y
>
> That accounts for the last three lines of the original output.
>
> So what about the "making s-h" line right before that? The difference
> between just running "d.rkt" and requiring it at the repl is that in the
> second case, we have one more compilation context to set up: the repl
> itself. That means one more instantiation of the compile-time parts of
> the modules (or "visit", as the docs term it).
>
> Hope that helps,
> Ryan
>
>
> On 09/24/2013 04:40 PM, Dmitry Pavlov wrote:
>> Jay,
>>
>> Section 1.1.10 does not really answer my question:
>> I had no doubts in the first place about phase 0 and
>> phase1 being separated from each other.
>>
>> I am not so sure about whether the phase 1 data
>> is shared between different "load chain" of a module.
>> That has to to with visits and instantiatiins I beleive.
>> I will keep reading, though would not mind if somebody
>> points me to the answer directly.
>>
>> Regards,
>>
>> Dmitry
>>
>> On Sep 24, 2013 11:47 PM, "Jay McCarthy" <jay.mccarthy at gmail.com
>> <mailto:jay.mccarthy at gmail.com>> wrote:
>>
>>     The details of your answer are in Reference section 1.1.10
>>
>>
>> http://docs.racket-lang.org/reference/eval-model.html#(part._module-eval-model)
>>
>>
>>     Basically, the runtime and compile time of every module is distinct
>>     and not shared between compiles of different modules. Racket
>>     guarantees that they are never shared, no matter how many modules are
>>     already (or not already) compiled when you start. You may think there
>>     is sharing, but there is not. Instead, when d runs it runs the syntax
>>     toplevel of b and c, despite having compiled them separately. (You
>>     could observe the difference if you changed your begin-for-syntax
>> code
>>     into code that happens to run during the expansion of b and c.)
>>
>>     The justification for this behavior is elaborated in Matthew Flatt's
>>     "Metaprogramming Time!" [1] and the paper "Composable and Compilable
>>     Macros" [2]
>>
>>     Jay
>>
>>     1. http://www.infoq.com/presentations/racket
>>     2. http://www.cs.utah.edu/plt/publications/macromod.pdf
>>
>>     Jay
>>
>>     On Tue, Sep 24, 2013 at 1:38 PM, Dmitry Pavlov <dpavlov at ipa.nw.ru
>>     <mailto:dpavlov at ipa.nw.ru>> wrote:
>>      > Hello,
>>      >
>>      > I have a problem that originates from the fact that I do not
>>      > really understand the innards of the mechanism of module loading.
>>      >
>>      > Basically, I want to share a hashtable stored in some module
>>      > between a number of other modules. Moreover, I want to do
>>      > that on the syntax level. In this example, I will do that
>>      > in parallel on run level and syntax level, showing problems
>>      > in the second case.
>>      >
>>      > ~~~~~ a.rkt:
>>      >
>>      > #lang racket
>>      > (provide h
>>      >          (for-syntax s-h))
>>      >
>>      > (define h (begin (printf "making h\n") (make-hash)))
>>      >
>>      > (define-for-syntax s-h  (begin (printf "making s-h\n")
>> (make-hash)))
>>      >
>>      >
>>      > ~~~~~ b.rkt:
>>      >
>>      > #lang racket
>>      >
>>      > (require "a.rkt")
>>      > (hash-set! h 1 "x")
>>      > (begin-for-syntax
>>      >   (hash-set! s-h 1 "xx"))
>>      >
>>      >
>>      > ~~~~~ c.rkt:
>>      >
>>      > #lang racket
>>      > (require "a.rkt")
>>      > (hash-set! h 2 "y")
>>      > (begin-for-syntax
>>      >   (hash-set! s-h 2 "yy"))
>>      >
>>      > ~~~~~ d.rkt:
>>      >
>>      > #lang racket
>>      > (require "a.rkt")
>>      > (require "b.rkt")
>>      > (require "c.rkt")
>>      >
>>      > (define-syntax (print-s-h stx)
>>      >   (syntax-case stx ()
>>      >     ((_)
>>      >      (for (((key val) s-h))
>>      >        (printf "~a : ~a\n" key val))
>>      >      #'(void))))
>>      >
>>      > (for (((key val) h))
>>      >   (printf "~a : ~a\n" key val))
>>      >
>>      > (print-s-h)
>>      >
>>      >
>>      >
>>      > What I get:
>>      >
>>      > making s-h
>>      > making s-h
>>      > making s-h
>>      > making s-h
>>      > making s-h
>>      > making s-h
>>      > making s-h
>>      > 1 : xx
>>      > 2 : yy
>>      > making s-h
>>      > making s-h
>>      > making h
>>      > 1 : x
>>      > 2 : y
>>      >
>>      >
>>      > What I see: on the execution level everything works as I want.
>>      > (Is it guaranteed to work that way?)
>>      >
>>      > On the syntax level, the hash table is created eight times instead
>>      > of (as I would expect) one, but still only one of the instances
>>      > is in action, and is shared across modules. Is it guaranteed to
>>      > work that way? In my real (more complicated) code a similar
>>      > hash table is not shared, and in effect, the "top" procedure gets
>>      > a fresh and empty instance of it, therefore I am in trouble.
>>      > I am wondering what are Racket's rules for sharing module data
>> on the
>>      > syntax level.
>>      >
>>      >
>>      > Regards,
>>      >
>>      > Dmitry
>>      > ____________________
>>      >  Racket Users list:
>>      > http://lists.racket-lang.org/users
>>
>>
>>
>>     --
>>     Jay McCarthy <jay at cs.byu.edu <mailto:jay at cs.byu.edu>>
>>     Assistant Professor / Brigham Young University
>>     http://faculty.cs.byu.edu/~jay
>>
>>     "The glory of God is Intelligence" - D&C 93
>>     ____________________
>>        Racket Users list:
>>     http://lists.racket-lang.org/users
>>
>>
>>
>> ____________________
>>    Racket Users list:
>>    http://lists.racket-lang.org/users
>>
>
>
>


Posted on the users mailing list.