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

From: Dmitry Pavlov (dpavlov at ipa.nw.ru)
Date: Tue Sep 24 15:38:21 EDT 2013

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

Posted on the users mailing list.