Racket: eval, namespace-attach-module vs. namespace-require
Asked Answered
N

1

5

Let's say I have a module "foo.rkt" which exports a struct foo, e.g.,

#lang racket (provide foo) (struct foo ())

In another module, I use "foo.rkt" but I'd also like to associate the binding to "struct foo" to another namespace (I don't use prefabs for various reasons, so I can't use namespace-require).

I thought that I could use namespace-attach-module as follows:

(define ns (make-base-namespace))
(namespace-attach-module (current-namespace) "foo.rkt" ns)
(eval '(foo) ns)

But that does not work, as namespace-mapped-symbols reveals that s is not bound in ns (if this is the only place to look for bindings). It does however work in the REPL. Why?

Nutwood answered 17/6, 2018 at 14:53 Comment(0)
H
6

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.

Heim answered 17/6, 2018 at 15:37 Comment(1)
Thank you very much, this is what I was looking for.Nutwood

© 2022 - 2024 — McMap. All rights reserved.