[racket] How to get a shared environment in different modules in compile time

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

Hello,

Suppose I am trying to have my own variant of (define),
which tags text comments to things that it defines.
I am keeping the comments in a hashtable for whatever
purpose, and in the following example I am just printing
them to the standard output:

~~~~~ defcom.rkt
#lang racket

(define-for-syntax comments (make-hash))
(define-syntax (def-with-comment stx)
   (syntax-case stx ()
     ((_ (name comment . params) . body)
      (hash-set! comments (syntax->datum #'name) (syntax->datum #'comment))
      #'(define (name . params) . body))))

(def-with-comment (my+ "addition" a b) (+ a b))
(def-with-comment (my- "subtraction" a b) (- a b))

(begin-for-syntax
   (for (((name val) comments))
   (printf "~a: ~a\n" name val)))

(printf "~a\n" (my- (my+ 3 4) 2))


That works great and prints:
my+: addition
my-: subtraction
5


The trouble starts when I split the macro, the definitions,
and the main program into separate modules.

~~~~~~~~ defcom1.rkt
#lang racket

(provide def-with-comment
          (for-syntax comments))

(define-for-syntax comments (make-hash))

(define-syntax (def-with-comment stx)
   (syntax-case stx ()
     ((_ (name comment . params) . body)
      (hash-set! comments (syntax->datum #'name) (syntax->datum #'comment))
      #'(define (name . params) . body))))

~~~~~~~~ defcom2.rkt
#lang racket

(require "defcom1.rkt")

(provide my+ my-)

(def-with-comment (my+ "addition" a b) (+ a b))
(def-with-comment (my- "subtraction" a b) (- a b))


~~~~~~~~ defcom3.rkt
#lang racket

(require "defcom1.rkt")
(require "defcom2.rkt")

(begin-for-syntax
   (for (((name val) comments))
   (printf "~a: ~a\n" name val)))

(printf "~a\n"(my- (my+ 3 4) 2))


It does not print my hash table.

I understand why it happens: when defcom2 compiles, it gets its own
instance of defcom1, which is "forgotten" during the compilation of
defcom3, and defcom3 gets a fresh instance of defcom1 with
an empty hashtable.

However, I do not see how to fix that. Does anybody?
What is the recommended way to do that sort of thing in Racket?

Regards,

Dmitry

Posted on the users mailing list.