There is a module that is utilitarian in nature, that is included in another other modules. These other modules are in turn included in yet other modules.
module A:
#lang racket
(require "utility.rkt")
module B:
#lang racket
(require "utility.rkt")
module C:
#lang racket
(require "A.rkt")
(require "B.rkt")
'utility' has some initialization code and a module variable that is intended to be shared by the utility code. Say for the sake of example,
utility maintains a collection of test functions:
(define test-routines '())
(define (test-name a-test) (symbol->string (object-name a-test)))
(define (test-hook a-test)
(display "hooking test: ") (displayln (test-name a-test))
(set! test-routines (cons a-test (remove a-test test-routines (λ(e f) (string=? (test-name e) (test-name f)))))))
[results (map test (reverse test-routines))]
[no-tests (length results)]
[result-flags (map cadr results)]
[error-count (count (λ(e) (not e)) result-flags)]
[all-passed (andmap (λ(e) e) result-flags)]
[all-passed (display "all ")(display no-tests) (displayln " passed")]
So what is happening here is that the module code initializes a global test list. Other modules which require utilities.rkt then call test-hook to hook in their test code. Then after all the modules are loaded, the application calls (test-all) to see that everything is running well.
However, it isn't working because the "utility.rkt" module initialization code is running multiple times, and each time clobbering (making new version?) of the test list. This behavior did not occur when the require call depth was only one deep, but now that it is two deep, it is happening.
racket@> (enter! "object.rkt")
hooking test: example-pass-test
...
(test-all) to run the tests
hooking test: and-form-test-0
hooking test: test-Λ-0
...
===> RUNNING INIT CODE IN MODULE A SECOND TIME:
hooking test: example-pass-test
...
hooking test: test-flatten-1
hooking test: test-replace-0
....
===> RUNNING INIT CODE IN MODULE A THIRD TIME:
hooking test: example-pass-test
hooking test: example-fail-test
....
Should it be like this? Is a module static (one copy) or is it like a class (new copy on invocation) actually I'm seeing a third behavior, static at one level deep, new instances at two levels deep (or just running the code again over the same instance?)