I assume the problem is to avoid instantiating the module in "foo.rkt" twice, since this leads to two incompatible structure definitions.
The function namespace-attach-module
is part of the puzzle, but it only attaches
the instantiated module to the namespace ns - that is the name "foo.rkt" is now associated with the correct instantiation of "foo.rkt". It however doesn't make the bindings available in ns - that is the job of namespace-require
.
Here is an example:
File: "computer.rkt"
#lang racket
(provide (struct-out computer))
(struct computer (name price) #:transparent)
File: "use-computer.rkt"
#lang racket
(require "computer.rkt") ; instatiate "computer.rkt"
(define ns (make-base-namespace))
(namespace-attach-module (current-namespace) "computer.rkt" ns) ; ns now knows the same instance
(define a-computer
(parameterize ([current-namespace ns])
(namespace-require "computer.rkt")
(eval '(computer "Apple" 2000) ns)))
(computer-name a-computer) ; works, since ns used the same instantiation of "computer.rkt"
The result of running this is:
"Apple"
Note that removing the namespace-attach-module
line leads to the error:
computer-name: contract violation;
given value instantiates a different structure type with the same name
expected: computer?
given: (computer "Apple" 2000)
since without the attachment, the namespace-require
will instatiate "computer.rkt" a second time leading to two incompatible structures begin declared.