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

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Tue Sep 24 15:47:20 EDT 2013

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> 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>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 93

Posted on the users mailing list.